0

Once the submit button is pressed, the information should be displayed in a list below (automatically sorted by last name) along with all the previous information that was entered. This way the application can function as a simple phone book.

This is what I have right now. I need to display entered values from input to the table under the respective sections -

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

const style = {
  table: {
    borderCollapse: 'collapse'
  },
  tableCell: {
    border: '1px solid gray',
    margin: 0,
    padding: '5px 10px',
    width: 'max-content',
    minWidth: '150px'
  },
  form: {
    container: {
      padding: '20px',
      border: '1px solid #F0F8FF',
      borderRadius: '15px',
      width: 'max-content',
      marginBottom: '40px'
    },
    inputs: {
      marginBottom: '5px'
    },
    submitBtn: {
      marginTop: '10px',
      padding: '10px 15px',
      border:'none',
      backgroundColor: 'lightseagreen',
      fontSize: '14px',
      borderRadius: '5px'
    }
  }
}

function PhoneBookForm({ addEntryToPhoneBook }) {
  return (
    <form onSubmit={e => { e.preventDefault() }} style={style.form.container}>
      <label>First name:</label>
      <br />
      <input 
        style={style.form.inputs}
        className='userFirstname'
        name='userFirstname' 
        type='text'
      />
      <br/>
      <label>Last name:</label>
      <br />
      <input 
        style={style.form.inputs}
        className='userLastname'
        name='userLastname' 
        type='text' 
      />
      <br />
      <label>Phone:</label>
      <br />
      <input
        style={style.form.inputs}
        className='userPhone' 
        name='userPhone' 
        type='text'
      />
      <br/>
      <input 
        style={style.form.submitBtn} 
        className='submitButton'
        type='submit' 
        value='Add User' 
      />
    </form>
  )
}

function InformationTable(props) {
  return (
    <table style={style.table} className='informationTable'>
      <thead> 
        <tr>
          <th style={style.tableCell}>First name</th>
          <th style={style.tableCell}>Last name</th>
          <th style={style.tableCell}>Phone</th>
        </tr>
      </thead> 
    </table>
  );
}

function Application(props) {
  return (
    <section>
      <PhoneBookForm />
      <InformationTable />
    </section>
  );
}

ReactDOM.render(
  <Application />,
  document.getElementById('root')
);

1 Answer 1

2

const { useState, useRef } = React

const style = {
  table: {
    borderCollapse: 'collapse'
  },
  tableCell: {
    border: '1px solid gray',
    margin: 0,
    padding: '5px 10px',
    width: 'max-content',
    minWidth: '150px'
  },
  form: {
    container: {
      padding: '20px',
      border: '1px solid #F0F8FF',
      borderRadius: '15px',
      width: 'max-content',
      marginBottom: '40px'
    },
    inputs: {
      marginBottom: '5px'
    },
    submitBtn: {
      marginTop: '10px',
      padding: '10px 15px',
      border:'none',
      backgroundColor: 'lightseagreen',
      fontSize: '14px',
      borderRadius: '5px'
    }
  }
}


function PhoneBookForm({ addEntryToPhoneBook }) {
  const name = useRef(null);
  const lastName = useRef(null);
  const phone = useRef(null);

  return (
    <form onSubmit={e => {
      e.preventDefault();
      console.log("pozzo");
      addEntryToPhoneBook(prev => ([...prev, { userFirstName: name.current.value, userLastName: lastName.current.value, userPhone: phone.current.value }]))
    }} style={style.form.container}>
      <label>First name:</label>
      <br />
      <input 
        style={style.form.inputs}
        className='userFirstname'
        name='userFirstname'
        ref={name}
        type='text'
      />
      <br/>
      <label>Last name:</label>
      <br />
      <input 
        style={style.form.inputs}
        className='userLastname'
        name='userLastname'
        ref={lastName}
        type='text' 
      />
      <br />
      <label>Phone:</label>
      <br />
      <input
        style={style.form.inputs}
        className='userPhone' 
        name='userPhone'
        ref={phone}
        type='text'
      />
      <br/>
      <input 
        style={style.form.submitBtn} 
        className='submitButton'
        type='submit' 
        value='Add User' 
      />
    </form>
  )
}

function InformationTable({ phoneBook }) {
  return (
    <table style={style.table} className='informationTable'>
      <thead> 
        <tr>
          <th style={style.tableCell}>First name</th>
          <th style={style.tableCell}>Last name</th>
          <th style={style.tableCell}>Phone</th>
        </tr>
      </thead>
       <tbody>
        {phoneBook.map(el => (
           <tr>
              <td>{el.userFirstName}</td>
              <td>{el.userLastName}</td>
              <td>{el.userPhone}</td>
           </tr>
        ))}
      </tbody>
    </table>
  );
}

function Application(props) {
  const [book, setBook] = useState([{ userFirstName: "toto", userLastName: "tozzi", userPhone: "0982798736" }]);
  
  return (
    <section>
      <PhoneBookForm addEntryToPhoneBook={setBook} />
      <InformationTable phoneBook={book} />
    </section>
  );
}

ReactDOM.render(
  <Application />,
  document.getElementById('test')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="test"></div>

You'll need to use a state that is shared between PhoneBookForm and InformationTable :

  const [book, setBook] = useState([]) // empty array for initialization

  return (
    <section>
      <PhoneBookForm addToPhoneBook={setBook} /> 
      <InformationTable phoneBook={book} />
    </section>
  );

and then inside the PhoneBookForm you'll add all the information inside the state during the onSubmit :

function PhoneBookForm({ addToPhoneBook }) {
  return (
    <form onSubmit={e => {
       e.preventDefault();
       addToPhoneBook((prev) => [...prev, { userFirstName: ........ }]);
       // here I used a function inside the setState to get access to the previous value of
       // the state, if you're not confortable with this i encourage you to look at spread
       // operator and the doc of useState
    }} style={style.form.container}>
      {...}
    </form>
  )
}

and finally you can build your table using the map function on the book props :

function InformationTable({ phoneBook }) {
  return (
    <table style={style.table} className='informationTable'>
      <thead> 
        <tr>
          <th style={style.tableCell}>First name</th>
          <th style={style.tableCell}>Last name</th>
          <th style={style.tableCell}>Phone</th>
        </tr>
      </thead>
      <tbody>
        {phoneBook.map(el => (
           <tr>
              <td>{el.userFirstName}</td>
              <td>{el.userLastName}</td>
              <td>{el.userPhone}</td>
           </tr>
        )}
      </tbody>
    </table>
  );
}
Sign up to request clarification or add additional context in comments.

5 Comments

Where is InfoTable getting the phonebook value
Because the error says its not recognizable
It's an uncontrolled form so you'll need to have a ref for all the input inside your form, I encourage you to read this to understand this concept : itnext.io/…
Its actually saying phoneBook.map is not a function now..
I just put a working example on my post, please look at it to see what did you have done wrong.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.