Reputation: 142
I want to figure out how to create simple React components that update based on changes that parent components pass to a child's props. I am able to achieve the desired result when I update the component state internally, but I want the component to be entirely controlled by its parent by way of changing its props. In regular React, this is trivial, but I have been unable to figure out how to accomplish this in an SSR Next.js app.
This is a general issue that will affect many components I intend to build, but for the sake of clarity I will focus on the one I am currently working on: a collapsable container with a boolean collapsed prop that determines whether or not the container is collapsed.
How can I make Next.js fire React lifecycle methods (particularly componentDidUpdate) in a child component when its parent updates its props, in this case toggling a boolean?
I have already looked into using getInitialProps, but according to the Next.js docs, this only works for pages. Also and unsurprisingly, it didn't work.
I have also experimented with componentWillUpdate, shouldComponentUpdate, and even getDerivedStateFromProps but I have had no luck with anything except having the component update its own state internally which is not an acceptable solution for my use case.
I have tried to create this component using both React.Component class extension syntax and stateless function syntax, but neither worked and there was no perceivable difference in their results.
I would like to work directly with the props and not involve state if possible, as the React docs suggest that updating state based on props is bad practice, not to mention it shouldn't be necessary.
render() {
return (
<div className={ styles.wrapper }>
<div
className={ styles.container }
data-collapsed={ this.props.collapsed }
>
</div>
</div>
);
}
}
The actually collapse effect is accomplished through CSS based on the value of the data-collapsed custom attribute. This solution works, so I did not include this code.
I omitted my failed lifecycle method attempts, but otherwise this should clearly be a very simple component. In my experience with vanilla React in the past, changing a child prop directly triggered a rerender, often without the need of any lifecycle method at all.
What I want is simple (I think): Have a parent component change the CollapsableContainer collapsed prop and have it update accordingly. What am I missing here?
Upvotes: 2
Views: 2467
Reputation: 142
I figured it out and it is a bit embarrassing. I was testing this solution using external variables rather than state variables in the parent. Like this:
let testBool = false;
class Example extends Component {
render() {
return (
<div>
<ComponentToUpdate
booleanProp={ testBool }
/>
<button
onClick={() => { testBool = !testBool; }}
>
Click
</button>
</div>
)
}
}
But now I am doing this:
class Example extends Component {
constructor(props) {
super(props);
this.state = {
testBool: false
}
}
render() {
return (
<div>
<ComponentToUpdate
booleanProp={ this.state.testBool }
/>
<button
onClick={() => { setState({ testBool: !this.state.testBool }) }}
>
Click
</button>
</div>
)
}
}
And it works. And now to the facepalm. Hopefully this helps someone else who may be experience mental flatulence.
Upvotes: 1