Reputation: 4362
In below code, state of Test is updating but its not re-rendering. I have updated the state of parent on button click on change of which I expected it to rerender the whole component including Button. But its not re-rendering Button. Need help wrt this. This is a test code and both classes are necessary.
import React from 'react';
class Button extends React.Component {
constructor(props){
super(props)
this.state = {
id : props.id
}
}
render() {
console.log('Button state id is', this.state.id)
return(
<div>
'hi ' + {this.state.id}
<br/>
<button type='submit' onClick={this.props.handleSubmit}>
submit
</button>
</div>
)
}
}
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
id: 1
}
this.changeId = this.changeId.bind(this)
}
changeId() {
let id = this.state.id
console.log('parent state id is', id)
this.setState({
id: ++id
})
}
render() {
return(
<Button id={this.state.id} handleSubmit={this.changeId}/>
)
}
}
EDIT: I have modified the code to remove obvious errors like not passing in changeId
function to Button
EDIT 2: Found the solution here: React Child Component Not Updating After Parent State Change componentWillReceiveProps
Upvotes: 1
Views: 24433
Reputation: 1396
The example for componentWillReceiveProps
worked in my case, when I wanted to update child component of React on setState
of parent component:
componentWillReceiveProps(props) {
this.setState({
currentID: props.currentID
});
}
Upvotes: 0
Reputation: 1557
For a number to re render in the child component you need to make following changes to your code:
In current scenario value of id in changeId function is event, so you can't do ++id. You have to update it to:
changeId() {
this.setState({
id: ++this.state.id
})
}
and for child component to re render the props value, you have to listen if there is any change in props. For that use componentDidUpdate lifecycle of react. Like this:
componentDidUpdate(prevProps){
if (this.props.id !== prevProps.id) {
this.setState({id: this.props.id});
}
}
The other way is don't store props.id in child state. Use it directly in render.
class Button extends React.Component {
render() {
return(
<div>
'hi ' + {this.props.id}
<br/>
<button type='submit' onClick={this.props.handleSubmit}>
submit
</button>
</div>
)
}
}
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
id: 1
}
this.changeId = this.changeId.bind(this)
}
changeId() {
this.setState({
id: ++this.state.id
})
}
render() {
return(
<Button id={this.state.id} handleSubmit={this.changeId}/>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />
Upvotes: 3
Reputation: 1659
We can further optimise the component by doing something like this -: Highlights -:
changeId() {
changed to changeId = () => {
(fat arrow notation), if we use this we don't need this.changeId = this.changeId.bind(this)
;import React, {Component} from 'react';
export default class Test extends React.Component {
constructor(props) {
super(props)
this.state = {
id: 1
}
}
changeId = () => {
this.setState({
id: ++this.state.id
})
}
render() {
return(
<div>
'hi ' + {this.state.id}
<br/>
<button type='submit' onClick={this.changeId}>
submit
</button>
</div>
)
} }
Upvotes: 0
Reputation: 407
You haven't actually passed handleSubmit
as a prop to the Button
component. Assuming you want changeId()
to be called when you click the button, try this:
class Test extends React.Component {
constructor(props) {
super(props)
this.state = {
id: 1
}
this.changeId = this.changeId.bind(this)
}
changeId() {
console.log('change id called', id)
this.setState({
id: ++id
})
}
render() {
return(
<Button id={id} handleSubmit={this.changeId}/>
)
}
}
Upvotes: 0