Reputation: 3989
In the following SideMenuRow
child div inside my SideMenuContainer
component, I'm calling the changeInfoList
method. The method is in the parent App.js
.
In App.js:
<SideMenuContainer changeInfoList={this.changeInfoList} genInfoList={this.state.genInfoList} groupedObjectsList={this.state.groupedObjectsList}/>
In SideMenuContainer.js:
<SideMenuRow onClick={this.props.changeInfoList(genInfoElement.name)}>
Here are the relevant sections of the App.js
code involving the method and state:
constructor(props) {
super(props);
this.state = {
genInfoList: [],
groupedObjectsList: [],
cardInfo: {
name: data[0].name
},
data: []
};
}
changeInfoList(rowName){
//change the card rendered based on which row is clicked
this.setState({
cardInfo: {
name: rowName
}
})
}
What's incorrect about the way I'm structuring this method that isn't allowing setState to work?
Upvotes: 0
Views: 59
Reputation: 15708
You're getting this error because the keyword this is not pointing to your component's execution context and it's current execution context does not have a method called setState()
You can approach this a couple of ways:
1) Define an arrow function like the following:
const changeInfoList = (rowName) => {
//change the card rendered based on which row is clicked
this.setState({
cardInfo: {
name: rowName
}
})
}
By using an arrow-function (non-binding this), the this keyword now points to the closest object, in this case your class component, which has a setState() method.
2) Bind your current function inside your component's constructor.
constructor(props) {
super(props);
this.state = {
genInfoList: [],
groupedObjectsList: [],
cardInfo: {
name: data[0].name
},
data: []
};
this.changeInfoList = this.changeInfoList.bind(this)
}
This explicitly tells your function that this is now pointed to your class component's context.
Now assuming you did either of these steps, you would then have to pass down changeInfoList into your child components:
In App.js:
<SideMenuContainer changeInfoList={this.changeInfoList} genInfoList={this.state.genInfoList} groupedObjectsList={this.state.groupedObjectsList}/>
In SideMenuContainer:
<SideMenuRow onClick={() => { this.props.changeInfoList(genInfoElement.name) }}>
Upvotes: 2
Reputation: 557
constructor(props) {
super(props);
this.state = {
genInfoList: [],
groupedObjectsList: [],
cardInfo: {
name: data[0].name
},
data: []
};
// Bind the function
this.changeInfoList = this.changeInfoList.bind(this)
}
changeInfoList(rowName){
//change the card rendered based on which row is clicked
this.setState({
cardInfo: {
name: rowName
}
})
}
Upvotes: 1