skip to Main Content

With React I’m trying to pass data from a child component into the parent component. So I’d like the user to be able to input data into the text fields (one in data1 and one in data2) in the child component and place them into the data set in the parent component.

I tried a test function just to log the state from the parent component to confirm it had passed along correctly but my console log reads test detects [object Object] and [object Object] and I can’t figure out why.

How can I pass information into data in the parent component?

PARENT COMPONENT


function Main() {

    const [data, setData] = useState({
      data1:'',
      data2:'',
      data3:'',
      data4:'',
    })


return(
   <div>
   Always here Content
   </div>

    <ChildComponent
      data={data}
      setData={setData}
    />
)}


Child Component


function childComponent({ data, setData }){

      const test = () => {
        console.log('test detects ' + {data} + ' and ' + {setData})
      }

    return(

        <div>
        Some Rotating Content
        </div>

        <div>
        <TextField 
            id="outline-basic" 
            label="data1"
            name="data1"
            value={data1}
          />

        <TextField 
            id="outline-basic" 
            label="data2"
            name="data2"
            value={data2}
          />

        </div>
       <button onClick={() => {test()}}>Submit</button>


    )
}

2

Answers


  1. use value={data.data1} because {data1} has no meaning, you want the value to be equal to the value of the property data1 of data

    you want to update the parent state when you make a change with the input, depending on e.target.name which should be equal to the name of the property in your state object and take advantage also of e.target.value we update the parent state.
    here { ...prev, [e.target.name]: e.target.value } we return a copy of prev but with the property "[e.target.name]" equal to e.target.value.
    what we return is its new value of the state and and prev is its current value

    with each update, you are rendering the two components, updating the state in the parent one, then passing it to the child, so when you console log it from the child you will always see the updated data, in fact, it is easier to see it from inputs values shown on the screen, those values are received from the parent state after each update.

    import { useState } from "react";
    
    const Main = () => {
      const [data, setData] = useState({
        data1: "",
        data2: "",
        data3: "",
        data4: "",
      });
    
      return <ChildComponent data={data} setData={setData} />;
    };
    
    export default Main;
    
    // make sure it starts with Capital letter
    const ChildComponent = ({ data, setData }) => {
      const test = () => {
        console.log("test detects ", data);
      };
    
      return (
        <>
          <input
            id="outline-basic"
            label="data1"
            name="data1"
            value={data.data1}
            onChange={(e) => {
              setData((prev) => {
                return { ...prev, [e.target.name]: e.target.value };
              });
            }}
          />
          <input
            id="outline-basic"
            label="data2"
            name="data2"
            value={data.data2}
            onChange={(e) => {
              setData((prev) => {
                return { ...prev, [e.target.name]: e.target.value };
              });
            }}
          />
    
          <button
            onClick={() => {
              test();
            }}
          >
            Submit
          </button>
        </>
      );
    };
    
    Login or Signup to reply.
  2. First you cannot log the data and setData together in the Child because, data is empty since you have not initialized it and setData is a function to initialize or assign value to the data.

    Second you cannot access the data1 directly since it is inside the data object. You need to use data.data1 to access it.

    Then Try to log the data in the Main Component since you want the data to be in that(parent)

    export function Main() {
      const [data, setData] = useState({
        data1: "",
        data2: "",
        data3: "",
        data4: ""
      });
    
      console.log(data);
    
      return <ChildComponent data={data} setData={setData} />;
    }
    

    In the ChildComponent you need to make the text fields as Controlled Inputs so that the State is updated whenever the input fields are modified

    export function ChildComponent({ data, setData }) {
    
      return (
        <div>
          <input
            type="text"
            id="outline-basic"
            label="data1"
            name="data1"
            value={data.data1}
            onChange={(e) => setData({ ...data, [e.target.name]: e.target.value })}
          />
    
          <input
            type="text"
            id="outline-basic"
            label="data2"
            name="data2"
            value={data.data2}
            onChange={(e) => setData({ ...data, [e.target.name]: e.target.value })}
          />
        </div>
      );
    }
    

    Now you will be able to see the Console Log in the Parent whenever you type something in the Text Fields in the Child component.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search