How to pass data from child component to its parent in ReactJS?
Asked Answered
G

21

436

I'm trying to send data from a child component to its parent as follow:

const ParentComponent = React.createClass({
    getInitialState() {
        return {
            language: '',
        };
    },
    handleLanguageCode: function(langValue) {
        this.setState({language: langValue});
    },

    render() {
         return (
                <div className="col-sm-9" >
                    <SelectLanguage onSelectLanguage={this.handleLanguage}/> 
                </div>
        );
});

and here is the child component:

export const SelectLanguage = React.createClass({
    getInitialState: function(){
        return{
            selectedCode: '',
            selectedLanguage: '',
        };
    },

    handleLangChange: function (e) {
        var lang = this.state.selectedLanguage;
        var code = this.state.selectedCode;
        this.props.onSelectLanguage({selectedLanguage: lang});   
        this.props.onSelectLanguage({selectedCode: code});           
    },

    render() {
        var json = require("json!../languages.json");
        var jsonArray = json.languages;
        return (
            <div >
                <DropdownList ref='dropdown'
                    data={jsonArray} 
                    value={this.state.selectedLanguage}
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
});

What I need is to get the selected value by user in the parent component. I'm getting this error:

Uncaught TypeError: this.props.onSelectLanguage is not a function

Can anyone help me to find the problem?

P.S. The child component is creating a dropdown from a json file, and I need the dropdown list to show both elements of the json array next to each other(like: "aaa,english" as the first choice!)

{  
   "languages":[  
      [  
         "aaa",
         "english"
      ],
      [  
         "aab",
         "swedish"
      ],
}
Gas answered 15/7, 2016 at 10:37 Comment(8)
<SelectLanguage onSelectLanguage={this.handleLanguage*Code*}/> a typo.Apologetic
@YuryTarabanko Thanks, but still getting the same errorGas
@DavinTryon How should I add it? I tried like this: handleLanguageCode: function(langValue) { this.setState({ language: langValue }).bind(this); }, But it returns an error: ncaught TypeError: Cannot read property 'bind' of undefinedGas
@DavinTryon createClass autobinds non react methods.Apologetic
@OP could you create a fiddle demonstrating the issue?Apologetic
Possible duplicate of How to pass props to {this.props.children}Magnetite
But is it valid to pass data from Child to Parent ? Per my understanding data should only from Parent to Child isn't itSpaniard
You are passing a wrong function to child component and your parent class doesn't have handleLanguage function. You can pass like this instead: <SelectLanguage onSelectLanguage={this.handleLanguageChange}/>. I think if a function is absent in a class its would would be None.Dowson
C
415

This should work. While sending the prop back you are sending that as an object rather send that as a value or alternatively use it as an object in the parent component. Secondly you need to format your json object to contain name value pairs and use valueField and textField attribute of DropdownList

Short Answer

Parent:

<div className="col-sm-9">
     <SelectLanguage onSelectLanguage={this.handleLanguage} /> 
</div>

Child:

handleLangChange = () => {
    var lang = this.dropdown.value;
    this.props.onSelectLanguage(lang);            
}

Detailed:

EDIT:

Considering React.createClass is deprecated from v16.0 onwards, It is better to go ahead and create a React Component by extending React.Component. Passing data from child to parent component with this syntax will look like

Parent

class ParentComponent extends React.Component {

    state = { language: '' }

    handleLanguage = (langValue) => {
        this.setState({language: langValue});
    }

    render() {
         return (
                <div className="col-sm-9">
                    <SelectLanguage onSelectLanguage={this.handleLanguage} /> 
                </div>
        )
     }
}

Child

var json = require("json!../languages.json");
var jsonArray = json.languages;

export class SelectLanguage extends React.Component {
    state = {
            selectedCode: '',
            selectedLanguage: jsonArray[0],
        }

    handleLangChange = () => {
        var lang = this.dropdown.value;
        this.props.onSelectLanguage(lang);            
    }

    render() {
        return (
            <div>
                <DropdownList ref={(ref) => this.dropdown = ref}
                    data={jsonArray} 
                    valueField='lang' textField='lang'
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
}

Using createClass syntax which the OP used in his answer Parent

const ParentComponent = React.createClass({
    getInitialState() {
        return {
            language: '',
        };
    },

    handleLanguage: function(langValue) {
        this.setState({language: langValue});
    },

    render() {
         return (
                <div className="col-sm-9">
                    <SelectLanguage onSelectLanguage={this.handleLanguage} /> 
                </div>
        );
});

Child

var json = require("json!../languages.json");
var jsonArray = json.languages;

export const SelectLanguage = React.createClass({
    getInitialState: function() {
        return {
            selectedCode: '',
            selectedLanguage: jsonArray[0],
        };
    },

    handleLangChange: function () {
        var lang = this.refs.dropdown.value;
        this.props.onSelectLanguage(lang);            
    },

    render() {

        return (
            <div>
                <DropdownList ref='dropdown'
                    data={jsonArray} 
                    valueField='lang' textField='lang'
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
});

JSON:

{ 
"languages":[ 

    { 
    "code": "aaa", 
    "lang": "english" 
    }, 
    { 
    "code": "aab", 
    "lang": "Swedish" 
    }, 
  ] 
}
Conciliatory answered 15/7, 2016 at 13:47 Comment(12)
Thanks Shubham, your answer fixed the issue, but it doesn't show the selected item in dropdown list. It's empty after that :/Gas
@Sarah While creating the dropDownList you assigned its value to be this.state.selectedLanguage and that is not initialised to any value. That may be the issue. Which DropdownList component are you using. If I know maybe I can work on that to resolve the issue.Conciliatory
You are right. The this.state.selectedLanguage seems to be always null :/ I'm using DropdownList from react-widgetsGas
@Sarah I have made a small change to the code, including the binding of value to onChange function ans setting an initial state value. Try this and tell me if it works for youConciliatory
Returns an error: Uncaught ReferenceError: value is not defined. I made this change: onChange={this.handleLangChange.bind(this, this.value)} and no error returns, but still it doesn't show the selected value :(Gas
Sarah, Y not try to debug it. Try and print jsonArray in console and check if data is present first.Conciliatory
Let us continue this discussion in chat.Conciliatory
Is this possible, if it start from a grand parentHighball
Is this an intended use of props? I'm new to React and web development, and everyone seems to be aggressive about downward dataflow: data only flows from parent to children, not the way around (although I'm certain that there's a need for this).Vertu
What if child is a function not a class?Tarentarentum
@Jesse Functional components can have methods too. The syntax would be different but the essence will remain the same.Conciliatory
@ShubhamKhatri Can you assist me on my post? #65691643Tarentarentum
S
156

To pass data from child component to parent component

In Parent Component:

getData(val){
    // do not forget to bind getData in constructor
    console.log(val);
}
render(){
 return(<Child sendData={this.getData}/>);
}

In Child Component:

demoMethod(){
   this.props.sendData(value);
 }
Shortwave answered 9/6, 2017 at 23:5 Comment(2)
Don't forget this.getData = this.getData.bind(this); in the constructor, as you may get this.setState is not a function if you want to manipulate the state in getData.Highpitched
I've improvised the code from the above given answer. Hope it helps. https://mcmap.net/q/80631/-how-to-pass-data-from-child-component-to-its-parent-in-reactjsKhan
G
122

Considering React Function Components and using Hooks are getting more popular these days , I will give a simple example of how to Passing data from child to parent component

in Parent Function Component we will have :

import React, { useState } from "react";

then

const [childData, setChildData] = useState("");

and passing setChildData (which do a job similar to this.setState in Class Components) to Child

return( <ChildComponent passChildData={setChildData} /> )

in Child Component first we get the receiving props

function ChildComponent(props){ return (...) }

then you can pass data anyhow like using a handler function

const functionHandler = (data) => {

props.passChildData(data);

}
Giavani answered 20/2, 2020 at 7:40 Comment(0)
L
37

in React v16.8+ function component, you can use useState() to create a function state that lets you update the parent state, then pass it on to child as a props attribute, then inside the child component you can trigger the parent state function, the following is a working snippet:

const { useState , useEffect } = React;

function Timer({ setParentCounter }) {
  const [counter, setCounter] = React.useState(0);

  useEffect(() => {
    let countersystem;
    countersystem = setTimeout(() => setCounter(counter + 1), 1000);

    return () => {
      clearTimeout(countersystem);
    };
  }, [counter]);

  return (
    <div className="App">
      <button
        onClick={() => {
          setParentCounter(counter);
        }}
      >
        Set parent counter value
      </button>
      <hr />
      <div>Child Counter: {counter}</div>
    </div>
  );
}

function App() {
  const [parentCounter, setParentCounter] = useState(0);

  return (
    <div className="App">
      Parent Counter: {parentCounter}
      <hr />
      <Timer setParentCounter={setParentCounter} />
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('react-root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>
Lacrimatory answered 15/5, 2020 at 15:24 Comment(0)
W
21

You can create the state in the ParentComponent using useState and pass down the setIsParentData function as prop into the ChildComponent.

In the ChildComponent, update the data using the received function through prop to send the data back to ParentComponent.

I use this technique especially when my code in the ParentComponent is getting too long, therefore I will create child components from the ParentComponent. Typically, it will be only 1 level down and using useContext or redux seems overkill in order to share states between components.

ParentComponent.js

import React, { useState } from 'react';
import ChildComponent from './ChildComponent';

export function ParentComponent(){
  const [isParentData, setIsParentData] = useState(True);

  return (
    <p>is this a parent data?: {isParentData}</p>
    <ChildComponent toChild={isParentData} sendToParent={setIsParentData} />
  );
}

ChildComponent.js

import React from 'react';

export function ChildComponent(props){

  return (
    <button onClick={() => {props.sendToParent(False)}}>Update</button>
    <p>The state of isParentData is {props.toChild}</p>
  );
};
Whinny answered 7/12, 2020 at 8:55 Comment(0)
H
17

I found the approach how to get data from child component in parents when i need it.

Parent:

class ParentComponent extends Component{
  onSubmit(data) {
    let mapPoint = this.getMapPoint();
  }

  render(){
    return (
      <form onSubmit={this.onSubmit.bind(this)}>
        <ChildComponent getCurrentPoint={getMapPoint => {this.getMapPoint = getMapPoint}} />
        <input type="submit" value="Submit" />
      </form>
    )
  }
}

Child:

class ChildComponent extends Component{
  constructor(props){
    super(props);

    if (props.getCurrentPoint){
      props.getCurrentPoint(this.getMapPoint.bind(this));
    }
  }

  getMapPoint(){
    return this.Point;
  }
}

This example showing how to pass function from child component to parent and use this function to get data from child.

Hards answered 19/3, 2017 at 9:0 Comment(0)
Z
11

from child component to parent component as below

parent component

class Parent extends React.Component {
   state = { message: "parent message" }
   callbackFunction = (childData) => {
       this.setState({message: childData})
   },
   render() {
        return (
            <div>
                 <Child parentCallback = {this.callbackFunction}/>
                 <p> {this.state.message} </p>
            </div>
        );
   }
}

child component

class Child extends React.Component{
    sendBackData = () => {
         this.props.parentCallback("child message");
    },
    render() { 
       <button onClick={sendBackData}>click me to send back</button>
    }
};

I hope this work

Zagreb answered 21/8, 2019 at 13:30 Comment(0)
A
10

Found a great and easy way to do this with input recently.

Essentially I just useState and then set onChange as a prop to the child comp it takes "value" as an argument and puts it into the useState "setVal" boom I got state change child -> parent every time

const Parent = () => {
  const [val, setVal] = useState("initial value")
  return(
    <>
    <Child onChange={(value)=> setVal(value)}/>
    <div>{val}</div>
    </>
  )
};

export default Parent;

const Child = (props) => {
  return(
  <button onClick={() => props.onChange("your value here") }>
  )
}
Algiers answered 21/11, 2021 at 22:41 Comment(0)
E
8

Here I am trying to explain in simplest way: I am updating the Parent Component counter from the Child Component.

Parent Component (PropsApp.jsx)

import React, { useState } from 'react'
import Child from './Child'

export default function PropsApp(){
   const [counter, setCounter] = useState(0)

   const updateMyCounter = () => {
       setCounter(counter + 1)
   }

   return(
    <>  
        <hr></hr>
        <h1>This is Parent</h1>
        <h2>{counter}</h2>
        <Child updateParent={updateMyCounter} />
    </>
   )
}

Child Component (Child.jsx)

export default function Child(props){

return(
    <>  
        <hr></hr>
        <h1>This is Child</h1>
        <button
            onClick={props.updateParent}
        >
            Update Parent Component
        </button>
    </>
   )
}

Click on the Update Parent Component and see the magic enter image description here

Ebracteate answered 25/4, 2021 at 17:2 Comment(0)
J
5

To pass data from a child component to a Parent component in React:

  1. Pass a function to the child from the parent that receives values.
  2. When the values change in the child component call the function with the updated values.

e.g.

const Parent = () => {

  const handleChange = values => {
     alert(JSON.stringify(values) );
     //do something with the values  
  }

  return (
    <Child handleChange={handleChange} />
  );
}

const Child = ({handleChange}) => {
    return (
        <button onClick={() => handleChange('values you wish to pass') }></button>
    );
}

NB: As of react 16 I would recommend using functional components in almost all cases.

Jack answered 25/7, 2022 at 15:7 Comment(0)
W
4

React.createClass method has been deprecated in the new version of React, you can do it very simply in the following way make one functional component and another class component to maintain state:

Parent:

const ParentComp = () => {
  
  getLanguage = (language) => {
    console.log('Language in Parent Component: ', language);
  }
  
  <ChildComp onGetLanguage={getLanguage}
};

Child:

class ChildComp extends React.Component {
    state = {
      selectedLanguage: ''
    }
    
    handleLangChange = e => {
        const language = e.target.value;
        thi.setState({
          selectedLanguage = language;
        });
        this.props.onGetLanguage({language}); 
    }

    render() {
        const json = require("json!../languages.json");
        const jsonArray = json.languages;
        const selectedLanguage = this.state;
        return (
            <div >
                <DropdownList ref='dropdown'
                    data={jsonArray} 
                    value={tselectedLanguage}
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
};
Whomsoever answered 6/3, 2019 at 11:27 Comment(1)
Just a note... you should reference the specific version of React instead of "the new version" to future proof this answer.Gama
Q
4

The idea is to send a callback to the child which will be called to give the data back

A complete and minimal example using functions:

App will create a Child which will compute a random number and send it back directly to the parent, which will console.log the result

const Child = ({ handleRandom }) => {
  handleRandom(Math.random())

  return <span>child</span>
}
const App = () => <Child handleRandom={(num) => console.log(num)}/>
Quarterhour answered 26/11, 2019 at 23:51 Comment(0)
C
2

You can even avoid the function at the parent updating the state directly

In Parent Component:

render(){
 return(<Child sendData={ v => this.setState({item: v}) } />);
}

In the Child Component:

demoMethod(){
   this.props.sendData(value);
}
Collazo answered 19/9, 2019 at 12:19 Comment(0)
C
2

Pass data from child to parent Component using Callback

You need to pass from parent to child callback function, and then call it in the child.

Parent Component:-TimeModal

  handleTimeValue = (timeValue) => {
      this.setState({pouringDiff: timeValue});
  }

  <TimeSelection 
        prePourPreHours={prePourPreHours}
        setPourTime={this.setPourTime}
        isPrePour={isPrePour}
        isResident={isResident}
        isMilitaryFormatTime={isMilitaryFormatTime}
        communityDateTime={moment(communityDT).format("MM/DD/YYYY hh:mm A")}
        onSelectPouringTimeDiff={this.handleTimeValue}
     />

Note:- onSelectPouringTimeDiff={this.handleTimeValue}

In the Child Component call props when required

 componentDidMount():void{
      // Todo use this as per your scenrio
       this.props.onSelectPouringTimeDiff(pouringDiff);  
  }
Colin answered 24/6, 2020 at 13:4 Comment(0)
S
2

You are passing a wrong function to child component and your parent class doesn't have handleLanguage function. You can pass like this instead: <SelectLanguage onSelectLanguage={this.handleLanguageChange}/>. I think if a function is absent in a class its would would be None. your parent component should be like this :

render() {
  return (
    <div className="col-sm-9">
      <SelectLanguage onSelectLanguage={this.handleLanguage} />
    </div>
  );
}
Sodomite answered 9/8, 2022 at 11:4 Comment(0)
C
1

Best way to pass data from child to parent component

child component

handleLanguageCode=()=>(langValue) {
  this.props.sendDatatoParent(langValue)
}

Parent

<Parent sendDatatoParent={ data => this.setState({item: data}) } />;

Caundra answered 26/11, 2020 at 14:0 Comment(0)
J
1
 import { useEffect, useState } from "react";
  
  export default function App() {
    const data = (data) => {
      console.log("data", data);
    };
  
    const myData = {
      name: "hi this is my data"
    };
  
    return <Form onSubmit={data} myDatasa={myData} />;
  }
  
  const Form = (props) => {
    console.log("myData", props.myDatasa.name);
  
    const [choreDesc, setChoreDesc] = useState();
    const handleSubmit = (e) => {
      e.preventDefault();
      props.onSubmit(choreDesc);
    };
  
    const handlechange = (e) => {
      setChoreDesc(e.target.value);
    };
  
    return (
      <form
        onSubmit={(e) => {
          handleSubmit(e);
        }}
      >
        <label>Chore description:</label>
        <br />
        <input
          name="choreDesc"
          type="text"
          value={choreDesc}
          onChange={handlechange}
        />
        <br />
        <input type="submit" value="Add Log" />
      </form>
    );
  };
  ```
Just answered 30/6, 2022 at 10:2 Comment(0)
P
0

Passing Data between Parent and Child Component in React Hook

Passing the function to child, and wait child passing back the value by calling parent's function

parent (../app.js)

import MyCOMP from "../component/MyCOMP"; //import child component

export default function MyMainPage() {
return(
  <>
    <MyCOMP 
      //pass function to child and wait child passback the changed value
      // 1.Click child component passing function to child

    ParentFunction={(x)=>{
      console.log('Child Pass Back Value',x)  

      // 3. Parent received data
      // after you get the value change you can ultilize another function, useEffect or useState 
    }}/>
  </>
)
}

child (../component/MyCOMP.js)

export default function MyCOMP({ParentFunction}){
  return(
    <>
      <button onClick={()=>{ 

        // 2. Child passing back value to parent 
        ParentFunction("Child reply ANSWER is ","fm 99.8");}}>Click Me</button>

    </>
  )
}

Result

after click the button, parent class show "fm 99.8" sting value (the child's value)

Please comment below, if it help you, or you got another idea

Psaltery answered 11/12, 2022 at 20:12 Comment(0)
D
0

In React, data is typically passed from a child component to a parent component using callback functions. The parent component can pass down a function as a prop to the child component, and the child component can call this function to send data back to the parent

ParentComponent.js

import React, { useState } from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = () => {
  const [dataFromChild, setDataFromChild] = useState(null);

  // Callback function to receive data from the child
  const handleDataFromChild = (data) => {
    setDataFromChild(data);
  };

  return (
    <div>
      <h2>Parent Component</h2>
      <p>Data from Child: {dataFromChild}</p>
      <ChildComponent sendDataToParent={handleDataFromChild} />
    </div>
  );
};

export default ParentComponent;

ChildComponent.js

import React from 'react';

const ChildComponent = ({ sendDataToParent }) => {
  const dataToSend = 'Hello from Child!';

  // Function to send data to the parent on some event (e.g., button click)
  const sendDataToParentOnClick = () => {
    sendDataToParent(dataToSend);
  };

  return (
    <div>
      <h3>Child Component</h3>
      <button onClick={sendDataToParentOnClick}>Send Data to Parent</button>
    </div>
  );
};

export default ChildComponent;

we have a ParentComponent and a ChildComponent. The ParentComponent has a state variable dataFromChild, which will store the data received from the child. It also has a callback function handleDataFromChild, which updates the state when called by the child.

The ChildComponent receives the sendDataToParent prop from its parent, which is a function. When the button is clicked, the sendDataToParentOnClick function is called, and it invokes the sendDataToParent function passed from the parent, sending the data back to the parent

Dana answered 27/7, 2023 at 6:19 Comment(0)
K
0

from the answer above : https://mcmap.net/q/80631/-how-to-pass-data-from-child-component-to-its-parent-in-reactjs

--parent--

export default function Parent() {
function parentCallback(data1: string) {
    console.log("parent : " + data1);
    setparentParm(data1);
  }

<ChildComponent childCallback={parentCallback} />

}

--child --
export type ChildProps = {
  childCallback: (data1: string) => void;
};

export function ChildComponent({ childCallback }: ChildProps) {
    childCallback(data1)
}
Khan answered 9/10, 2023 at 21:3 Comment(0)
S
0

To pass data from child to parent component by using callback function in prop in parent component and then pass data from child component by calling these function.

// Child
const Button = ({ text, onButtonClick }) => {
    return <button onClick={() => onButtonClick("hello")}>{text}</button>;
};

// Parent
const App = () => {
    const onButtonClick = (value) => {
        console.log("OnButtonClick in parent", value);
    };

    return (
        <div>
            App <Button text="Add" onButtonClick={onButtonClick} />
        </div>
    );
};

export default App;
Secular answered 30/3 at 8:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.