javascripthtmlreactjsformsreact-hooks

How do i pass form input values from child component to the father component in REACT?


i just started with react, specifically i am trying to use forms, i tried to make a simple project, where i got a form component with some inputs, once i click the submit button it should pass the inputs value to the father component (app) and it should render it in a custom list component that i wrote. The only problem is that when i try to access the event value it comes out as undefined, what am i doing wrong?

Following is my code, for simplicity sake i am trying to render just the first imput for now

import './App.css';



function Form({onChangeName}) {

    return (
        <div className="container">
          <h1>
            Hello 
          </h1>
          <form onSubmit={onChangeName}>
            <input name="fName" placeholder="First Name"  />
            <input name="lName" placeholder="Last Name"  />
            <input name="email" placeholder="Email"  />
            <button type="submit">Submit</button>
          </form>
        </div>
      );
}

export default Form;

:

import List from './List';
import './App.css';
import Form from './Form';
import { useState } from 'react';

function App() {

  const [contact, setContact] = useState({
    fName: "",
    lName: "",
    email: ""
})



function onChangeName(event){
  const { name, value } = event.target;
  console.log(value)
  setContact({
    fname: value,
    lName: "",
    email: ""
  })
}


  return (
    <div className="App">
      <Form onChangeName={onChangeName} fName={contact.fName} lName={contact.lName} email={contact.email} />
      <List fName={contact.fName} lName={contact.lName} email={contact.email}/>
    </div>
  );
}

export default App;

import logo from './logo.svg';
import './App.css';

function List({fName,lName,email}) {
    return(
        <ul>
            <li>{fName}</li>
            <li>{lName}</li>
            <li>{email}</li>
        </ul>
    )
   
}

export default List;


Solution

  • The issue you're facing is due to how you're handling the form submission and accessing the event value in your Form component. Here's how you can modify your code to make it work as intended

    1. In your Form component, you should use the useState hook to manage the form input values and handle changes to the input fields.

    2. In the Form component, you can use the onChange event handler to update the form state when input values change.

    3. Modify the onChangeName function to prevent the default form submission behavior and pass the current form state to the App component.

    Form.js

    import React, { useState } from 'react';
    
    function Form({ onSubmit }) {
        const [formData, setFormData] = useState({
            fName: '',
            lName: '',
            email: '',
        });
    
        const handleInputChange = (event) => {
            const { name, value } = event.target;
            setFormData({
                ...formData,
                [name]: value,
            });
        };
    
        const handleSubmit = (event) => {
            event.preventDefault();
            onSubmit(formData); // Pass the form data to the parent component
        };
    
        return (
            <div className="container">
                <h1>Hello</h1>
                <form onSubmit={handleSubmit}>
                    <input
                        type="text"
                        name="fName"
                        placeholder="First Name"
                        value={formData.fName}
                        onChange={handleInputChange}
                    />
                    <input
                        type="text"
                        name="lName"
                        placeholder="Last Name"
                        value={formData.lName}
                        onChange={handleInputChange}
                    />
                    <input
                        type="email"
                        name="email"
                        placeholder="Email"
                        value={formData.email}
                        onChange={handleInputChange}
                    />
                    <button type="submit">Submit</button>
                </form>
            </div>
        );
    }
    
    export default Form;
    

    In the above code:

    1. We use the useState hook to create a formData state object that stores the values of the form fields.

    2. The handleInputChange function is called when any input field changes, and it updates the corresponding field in the formData state.

    3. The handleSubmit function prevents the default form submission and calls the onSubmit prop function, passing the current formData.

    Now, in your App component, you can update the onChangeName function and pass the form data to the List component:

    App.js

    import React, { useState } from 'react';
    import Form from './Form';
    import List from './List';
    
    function App() {
      const [contact, setContact] = useState({
        fName: '',
        lName: '',
        email: '',
      });
    
      const onChangeName = (formData) => {
        setContact(formData);
      };
    
      return (
        <div className="App">
          <Form onSubmit={onChangeName} />
          <List fName={contact.fName} lName={contact.lName} email={contact.email} />
        </div>
      );
    }
    
    export default App;
    

    List.js

    import logo from './logo.svg';
    import './App.css';
    
    function List({ fName, lName, email }) {
        return (
            <ul>
                <li>{fName}</li>
                <li>{lName}</li>
                <li>{email}</li>
            </ul>
        )
    
    }
    
    export default List;
    

    With these modifications, your code should work as expected, and the input values from the Form component will be correctly passed to the List component for rendering.