5 ms·
I love hooks, but I think they made a few mistakes. The weirdness around useEffect having different behavior with no second argument vs [] is one of them. And
by ajkjk 4y ago
I love hooks, but I think they made a few mistakes. The weirdness around useEffect having different behavior with no second argument vs [] is one of them.
And they should have included a useUnloadEffect() by default, even though it's trivial to write, just for clarity. It's way too easy to miscount the number of ()s in useEffect(() => () => {}, []);
They also should have included a few other basic hooks, like useStableValue() for just computing a constant once on first render.
I hate the name `componentDidMount` though. useEffect seems much better to me.
- kareemsabri 4y agouseRef is useStableValue
- ajkjk 4y agoNot quite, having to use for current everywhere is just annoying, and it doesn't allow for a one-time constructor function.
- kareemsabri 4y agoWhy do you have to use current everywhere? You can do const { current: myStableValue } = useRef(computation); Not sure what you mean by one time constructor function, but you can pass the result of a function to initial value. const { current: myStableValue } = useRef((() => { //called once })());
- tshaddox 4y agoThis is incorrect. useRef takes an initialValue argument, but it does not treat functions as lazy initializers like useState does. If you pass a function to useRef, you’re just going to get that function as the initial value. If you want to lazily initialize a ref, you need to manually check if it has been initialized and run your expensive code if it hasn’t. Dan Abramov provides what appears to be a pattern officially recommended by the React team: https://github.com/facebook/react/issues/14490#issuecomment-454973512 https://github.com/facebook/react/issues/14490#issuecomment-...
- kareemsabri 4y agoIt's not a function, it's an immediately-invoked function expression. Edit: I guess it would be a bit inefficient to invoke the IIFE every render just to initialize the value once. Probably better to use useMemo with [] as the dependency list then, either one achieves the same result.
- tshaddox 4y agoI missed that you were immediately invoking the function expression. But yes, that doesn't save you from running the expensive calculation every subsequent render.
- graftak 4y agoI always do `const [stableValue] = useState(() => ...)`. It’s clear, simple, and easy to promote to an interactive value.
- AgentME 4y agoIt seems like almost always if you want to do anything during unmount, it's cleaning up something you set up in a useEffect call, which you also want to do any time the useEffect call's dependency list changes, so it being part of the useEffect hook helps programmers fall into the pit of success. React's older class-based components had the unmount handling separate (componentWillUnmount), and in my experience on a large React codebase, many if not most components using componentWillUnmount were subtly flawed and failed to handle certain cases where props or state updated in a way that should have caused effects to be cleaned up or adjusted. React's useEffect hook way of grouping up effects with their own cleanup code helps people handle these cases correctly even without realizing it sometimes.