I'm having some trouble updating nested components in my tree structure. I have created the following minimal example to illustrate the problem: Codesandbox.io
For completeness sake, this is the component that's being nested:
class Node extends React.Component {
constructor(props) {
super(props);
this.state = {
selected: props.selected
};
this.toggleSelected = this.toggleSelected.bind(this);
}
toggleSelected() {
this.setState({
selected: !this.state.selected
});
}
render() {
return (
<>
<div onClick={this.toggleSelected}>
Selected: {this.state.selected ? "T" : "F"}, Depth: {this.props.depth}
</div>
{this.props.depth < 5 && (
<Node selected={this.state.selected} depth={this.props.depth + 1} />
)}
</>
);
}
}
Nodes in the tree should be selectable on click and I'd like to toggle the selected state in all children (recursively) aswell. I thought I could do this by passing this.state.selected
via props to the child/children, unfortunately this doesn't seem to work.
The children get re-rendered, however using their old state (understandibly, as they're not being re-initialized via the constructor). What would be the correct way to handle this?
I've tried passing the key
prop to the nodes aswell to help react distinguish the elements, to no avail.
Edit: Here are a few examples of desired behaviour:
Consider this tree:
[ ] Foo
[ ] Foo A
[ ] Foo A1
[ ] Foo A2
[ ] Foo B
[ ] Foo B1
[ ] Foo B2
Expected result when checking "Foo"-Node:
[x] Foo
[x] Foo A
[x] Foo A1
[x] Foo A2
[x] Foo B
[x] Foo B1
[x] Foo B2
Expected result when checking "Foo A"-Node:
[ ] Foo
[x] Foo A
[x] Foo A1
[x] Foo A2
[ ] Foo B
[ ] Foo B1
[ ] Foo B2
Any tips / hints in the right direction are appreciated.
You should use getDerivedStateFromProps
like this:
constructor(props) {
super(props);
this.state = {
selected: props.selected,
propsSelected: props.selected
};
this.toggleSelected = this.toggleSelected.bind(this);
}
static getDerivedStateFromProps(props, state) {
if (props.selected !== state.propsSelected)
return {
selected: props.selected,
propsSelected: props.selected
};
}
We always store the prevProp in state. Whenever we encounter a change in the props that are stored in the state and the props coming from the parent, we update the state part (selected
) being controlled both from parent and the component itself and we also preserve the props at that point, in state for future diffing.
Usually a component which can be controlled from both the parent and itself will involve a logic of this sort. An input component found in most react component libraries is an ideal example.
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