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 ponent 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 ponentWillReceiveProps
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 ponent 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 ponentWillReceiveProps
- where is this id id={id} – cuongtd Commented Aug 6, 2019 at 6:27
- Did you forget passing handleSubmit={this.changeId} to your <Button> ponent in render if Test ponent? And I think it should be {this.state.id} not just {id} – G_S Commented Aug 6, 2019 at 6:30
-
id
is not defined inchangeId()
– Siddhartha Chowdhury Commented Aug 6, 2019 at 6:31 - May not be related to answering this question but worth mentioning here. @xploreraj, this is why I like using TypeScript along with React. It is much clearer as to what is there in our Props. You define props as an interface and declare the properties it is going to have. Same is the case with state. – Raja Malik Commented Aug 6, 2019 at 6:40
-
yes, this is just code for this question, it should be
this.state.id
– xploreraj Commented Aug 6, 2019 at 7:12
4 Answers
Reset to default 3For a number to re render in the child ponent 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 ponent to re render the props value, you have to listen if there is any change in props. For that use ponentDidUpdate lifecycle of react. Like this:
ponentDidUpdate(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./ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />
You haven't actually passed handleSubmit
as a prop to the Button
ponent. 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}/>
)
}
}
We can further optimise the ponent by doing something like this -: Highlights -:
changeId() {
changed tochangeId = () => {
(fat arrow notation), if we use this we don't needthis.changeId = this.changeId.bind(this)
;- Don't really need another ponent specially for button, can bine it in same ponent.
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>
)
} }
The example for ponentWillReceiveProps
worked in my case, when I wanted to update child ponent of React on setState
of parent ponent:
ponentWillReceiveProps(props) {
this.setState({
currentID: props.currentID
});
}