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" ], }
While there is no direct way to pass data from the child to the parent component, there are workarounds. The most common one is to pass a handler function from the parent to the child component that accepts an argument which is the data from the child component. This can be better illustrated with an example.
We can get child component values in the parent component by creating a reference to the child component using the @ref directive in the Parent component. Using the reference instance, you can access the child component values in the parent.
You can't pass props from child to parent in React, it's only one way (from parent to child). You should either: Put the state in the parent component and manipulate it from the child component by passing the setter function in the props.
You may access the child state by passing a callback to the child component. Now if you click the button in the child component, you will execute the function passed from the parent and have access to the child component's state variables.
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" }, ] }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With