3 ms·
> useEffect returns a teardown function which happens to correlate with unmount when an empty array is passed. I believe this teardown function runs on unmount
by pcthrowaway 4y ago
> useEffect returns a teardown function which happens to correlate with unmount when an empty array is passed.
I believe this teardown function runs on unmount whether or not the dependency array is empty.
- NTARelix 4y agoThis is correct, but I think the point nickdandakis was trying to make is that useEffect does not directly correlate with componentDidUnmount because useEffect's returned callback could be called in the middle of the component's lifecycle, not only when the component unmounts.
- pcthrowaway 4y agoErr.. no, you pass a callback (let's call it the effect callback) that returns a callback (the cleanup callback) to useEffect. The effect callback gets called when the component mounts, and when dependencies (if any) change. The cleanup callback gets called when the dependency unmounts (and will not be called at other times in the lifecycle) edit: I'm wrong, the cleanup is also called when dependencies change, just not on mount.. eg. it gets called before the effect callback being called again. In other words, the cleanup function is called on unmount when useEffect is called with an empty array, and if useEffect has dependencies, it will also be called when those dependencies change
- knodi123 4y agoYes, you're correct, and he got it wrong when talking about it. This kind of goes towards my point. useEffect works, and it works great. It's flexible and powerful - but it's cryptic as hell, and the interface is just "memorize it because you have to", not something more intuitive. What if useEffect required a 2nd argument, but you had the option to pass in self, which would still offer the onMount behavior, by mirroring the way the other form of it worked? Bada-bing, now there's no exception to the rule. What if the 2nd argument was a named argument, like "trigger"? Now it's self-documenting. What if the teardown function as an optional 3rd argument with a name, too? Now it's easy to glance at a useEffect and tell whether it's declaring a teardown without carefully reading the body. etc etc. He says "useRef offering a connection to DOM elements is just sugar", but that's not sweet, to me. There's no reason one thing should do two totally different things. That's exactly what I'm complaining about.
- dceddia 4y agoOh hey, that's me! :wave: I definitely agree useEffect is awfully cryptic and easy to get wrong, and I'm happy to be corrected... but I'm not sure how I'm wrong about it running on every render when there's no 2nd argument? I kinda wish they'd made it easier to do the common operations like onMount and onUnmount by providing some simplified wrappers around useEffect (with less power comes less responsibility... or something). Of course we can make custom hooks for those, but having the well-trodden paths be paved is always nice.
- pcthrowaway 4y agoI misunderstood what you were saying about it running on unmount when the dependency array is empty. Of course, it does run on unmount when the dependency array is empty, and it runs on unmount when there are dependencies in the dependency array. But upon re-reading what you said, I think your intent was that it's comparable to componentWillUnmount() in class-based React only when the dependency array is empty (because otherwise the cleanup function also gets called when dependencies change). My apologies, as I never really used class-based React, so the distinction was lost on me (and also forgot about the cleanup function being called between useEffect callback calls)
- dceddia 4y agoOh gotcha, no worries. I'm not sure if you meant to reply to me anyway, my comment was in regards to knodi123's original comment that linked to an article of mine and said it was wrong about when useEffect re-renders – but the comment was edited and that part is gone, so now mine looks entirely crazy haha.
- knodi123 4y agoI edited it because I realized I was wrong - I was confused by the difference between no 2nd argument, and [] for the 2nd argument. But again - as a full time professional web developer, who has being using React for a few years, I think that also goes towards my point. ;-)
- v0idzer0 4y agoIt does, but it runs on more than just unmount when the dependency array is not empty. It runs anytime any dependency in the array changes. This is an important distinction. For example, event listeners added in useEffect will be removed anytime a dependency changes. Then a re-render will occur and they will be added back in the next useEffect body execution. This differs from componentDidUnmount which obviously only runs on unmount and never in the render cycle