TkDodo / blog-comments

6 stars 1 forks source link

blog/simplifying-use-effect #15

Closed utterances-bot closed 2 years ago

utterances-bot commented 3 years ago

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

rosemaze commented 3 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...

TkDodo commented 3 years ago

Ah yes, I could've been a bit more specific, stating what will happen if you leave out the dependency array :)

JulesBlm commented 2 years ago

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.

JulesBlm commented 2 years ago

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?

TkDodo commented 2 years ago

@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.

JulesBlm commented 2 years ago

@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?

TkDodo commented 2 years ago

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.