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

Reactjs

Reactjs Problem Overview


I'm trying to send data from a child component to it's 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"      ],
}

Reactjs Solutions


Solution 1 - Reactjs

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" 
    }, 
  ] 
}

Solution 2 - Reactjs

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);
 }

Solution 3 - Reactjs

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);

}

Solution 4 - Reactjs

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>

Solution 5 - Reactjs

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>
  );
};

Solution 6 - Reactjs

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.

Solution 7 - Reactjs

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

Solution 8 - Reactjs

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

Solution 9 - Reactjs

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") }>
  )
}

Solution 10 - Reactjs

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>            
        );
    }
};

Solution 11 - Reactjs

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)}/>

Solution 12 - Reactjs

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);  
  }

Solution 13 - Reactjs

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);
}

Solution 14 - Reactjs

Best way to pass data from child to parent component

child component

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

Parent

this.setState({item: data}) } />;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBirishView Question on Stackoverflow
Solution 1 - ReactjsShubham KhatriView Answer on Stackoverflow
Solution 2 - ReactjsManisha TanView Answer on Stackoverflow
Solution 3 - ReactjsShayan MoghadamView Answer on Stackoverflow
Solution 4 - ReactjsROOTView Answer on Stackoverflow
Solution 5 - ReactjsShafie MukhreView Answer on Stackoverflow
Solution 6 - ReactjsMrDuDuDuView Answer on Stackoverflow
Solution 7 - ReactjsManoj RanaView Answer on Stackoverflow
Solution 8 - ReactjsRahul SarmaView Answer on Stackoverflow
Solution 9 - ReactjslampshedView Answer on Stackoverflow
Solution 10 - ReactjsSania Khushbakht JamilView Answer on Stackoverflow
Solution 11 - ReactjsFabien SaView Answer on Stackoverflow
Solution 12 - ReactjsKeshav GeraView Answer on Stackoverflow
Solution 13 - ReactjsBanzyView Answer on Stackoverflow
Solution 14 - ReactjsRuban DharmarajView Answer on Stackoverflow