Closed utterances-bot closed 2 years ago
The last way is quite hardcore, at first I thought wait a minute, what happens if payload
changes? The useEffect
doesn't have it as a dependency. The effect will not run! Then I googled, what happens if we don't pass a second argument for a useEffect
, and the answer is it will run every single render. Then looking at the code again, oh there is a condition inside to control when the effect will run. That is pretty cool, I will bear this pattern in mind.
Having said that, I do like having an array of dependencies because when I'm reading someone else's code, I can ask, do I care what this particular useEffect
is doing and I'm lazy to read all the code inside the block... I can check the dependencies array. If it is [], I know it does something on mount. If it doesn't have the variable I'm interested in I can just skip it.... so listing stuff in the dependency array could save code maintenance time...
Ah yes, I could've been a bit more specific, stating what will happen if you leave out the dependency array :)
Excellent post 👏 It inspired me make this little mnemonic for writing proper useEffects:
Never thought about naming the effect callback but it seems like a pretty sensible thing to do, it makes the intention of it more clear. I think moving each useEffect into a custom hook may be taking it litlle too far. Though there are people who take this a step further.
And small heads up: There's a typo in the second title: singe is missing an L.
Also, I sometimes found myself using usePrevious()
to check if an effect callback should run: if (current !== previous)
. It does the job but I feel it may be "thinking in lifecycles" too much (componentDidUpdate
), it feels a bit against the grain. What you do you think about this?
@JulesBlm I've never had to usePrevious
. I also think it might go against the rules-of-react, because it reads from a ref during render, which is technically not allowed.
@TkDodo thanks you for your reply, I had a feeling usePrevious
was icky. I wasn't aware that reading refs during render wasn't allowed. It's not really clear to me why it is bad. Are there are any downsides/risks to it now? Or will there be in the future with concurrent mode for example?
I wasn't aware that reading refs during render wasn't allowed. It's not really clear to me why it is bad. Are there are any downsides/risks to it now? Or will there be in the future with concurrent mode for example?
yes, concurrent mode (startTransition for example) can be troublesome. A ref
should be treated like an external store. There was a great talk from @dai-shi just two days ago about the problems with reading from external stores at react-conf, you can watch it here.
Simplifying useEffect | TkDodo's blog
useEffect hooks can be hard to reason about, but I have 5 principles that can help to manage them
https://tkdodo.eu/blog/simplifying-use-effect