Issue
This Content is from Stack Overflow. Question asked by Esoteric
There’s something fundamental I’m missing about how React triggers re-render when state is updated in a parent.
See attached codepen:
https://codepen.io/esoteric43/pen/poVPROQ
class App extends React.Component {
initState() {
let states = {}
for(let i = 0 ; i < 5; i++) {
states[i] = { selectedStatus: 'unselected'}
}
return states;
}
constructor(props) {
super(props);
this.state = {
states: this.initState()
};
this.updateStates = this.updateStates.bind(this);
}
updateStates(s) {
this.setState({
states: s
})
}
render() {
return (
<div>
<StateSelections states={this.state.states} updateStates={this.updateStates}/>
</div>
);
}
}
class StateSelections extends React.Component {
constructor(props) {
super(props);
this.state = {
stateSelections: [
<StateSelectionWrapper key={1} states={this.props.states} updateStates={this.props.updateStates}/> ,
<StateSelectionWrapper key={2} states={this.props.states} updateStates={this.props.updateStates}/>
]
}
}
render() {
return (
<div>
{this.state.stateSelections}
</div>
);
}
}
class StateSelectionWrapper extends React.Component {
render() {
return (
<div>
<StateSelection states={this.props.states} updateStates={this.props.updateStates} />
</div>
)
}
}
class StateSelection extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.executeCallback = (c) => props.updateStates(c);
}
handleClick(s) {
let copiedState = JSON.parse(JSON.stringify(this.props.states));
//let copiedState = this.props.states;
if (copiedState[s].selectedStatus === 'unselected') {
copiedState[s].selectedStatus = 'selected';
} else {
copiedState[s].selectedStatus = 'unselected';
}
this.executeCallback(copiedState);
}
renderState(s) {
if (this.props.states == null) {
return;
}
let color;
if (this.props.states[s].selectedStatus === 'unselected' ) {
color = 'white';
} else {
color = 'red';
}
return (
<S key={s} value={s} color={color} onClick={() => this.handleClick(s)} />
)
}
render() {
return (
<div>
{this.renderState(0)}
{this.renderState(1)}
{this.renderState(2)}
{this.renderState(3)}
{this.renderState(4)}
</div>
);
}
}
function S(props) {
return (
<button style={{backgroundColor: props.color}} onClick={props.onClick}>{props.value}</button>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<App />
);
When handleClick is called, the cells in both rows should be updated to red since both classes use the same state from the parent. The code is setting the states’ selectedStatus to ‘selected’ and passing the state values to the executeCallback method which is indeed calling the parent’s updateStates function. Unfortunately setState isn’t triggering a re-render of the view.
I’m missing something about how to share state among two children and how to get those children to update when the parent’s state is updated.
Solution
This question is not yet answered, be the first one who answer using the comment. Later the confirmed answer will be published as the solution.
This Question and Answer are collected from stackoverflow and tested by JTuto community, is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.