Lets say I have some state that is dependent on some other state (eg when A changes I want B to change).
Is it appropriate to create a hook that observes A and sets
For future purposes, this may help too:
It's ok to use setState in useEffect you just need to have attention as described already to not create a loop.
But it's not the only problem that may occur. See below:
Imagine that you have a component Comp that receives props from parent and according to a props change you want to set Comp's state. For some reason, you need to change for each prop in a different useEffect:
DO NOT DO THIS
useEffect(() => {
setState({ ...state, a: props.a });
}, [props.a]);
useEffect(() => {
setState({ ...state, b: props.b });
}, [props.b]);
It may never change the state of a as you can see in this example: https://codesandbox.io/s/confident-lederberg-dtx7w
The reason why this happen in this example it's because both useEffects run in the same react cycle when you change both prop.a and prop.b so the value of {...state} when you do setState are exactly the same in both useEffect because they are in the same context. When you run the second setState it will replace the first setState.
DO THIS INSTEAD
The solution for this problem is basically call setState like this:
useEffect(() => {
setState(state => ({ ...state, a: props.a }));
}, [props.a]);
useEffect(() => {
setState(state => ({ ...state, b: props.b }));
}, [props.b]);
Check the solution here: https://codesandbox.io/s/mutable-surf-nynlx
Now, you always receive the most updated and correct value of the state when you proceed with the setState.
I hope this helps someone!