First off what you did wasn't wrong, with that in mind read the following from the React docs:
There should be a single “source of truth” for any data that changes in a React application. Usually, the state is first added to the component that needs it for rendering. Then, if other components also need it, you can lift it up to their closest common ancestor. Instead of trying to sync the state between different components, you should rely on the top-down data flow.
Lifting state involves writing more “boilerplate” code than two-way binding approaches, but as a benefit, it takes less work to find and isolate bugs.
So, the idea is to only have the parent have full control over the state, the child should receive the parent's state and control to that state as props. This way if there's a bug, you always know where to look for - the parent. You can grant control to the state via props by wrapping the setter in a function in the parent. Doing so will also allow you to control how the child mutates the parent's state too.
TLDR: Wrapping the setter in a function and passing it as a prop, then calling it in the child makes it look like the parent is changing the state, not the child.
First off what you did wasn't wrong, with that in mind read the following from the React docs:
So, the idea is to only have the parent have full control over the state, the child should receive the parent's state and control to that state as props. This way if there's a bug, you always know where to look for - the parent. You can grant control to the state via props by wrapping the setter in a function in the parent. Doing so will also allow you to control how the child mutates the parent's state too.
TLDR: Wrapping the setter in a function and passing it as a prop, then calling it in the child makes it look like the parent is changing the state, not the child.
Makes sense, thanks for the detailed explanation :)