3 ms·
I didn't like Hooks out of principle when I first read about them. I still get slight heebie-jeebies when I think about the fact that they rely on calling-order
by brundolf 5y ago
I didn't like Hooks out of principle when I first read about them. I still get slight heebie-jeebies when I think about the fact that they rely on calling-order for identity. But having now used them for six months, I can't deny the practical benefits they bring.
I think it helps to not think of them as "just a way of letting you write all your components as functions". That was always a red herring; even before hooks, React "functional components" were impure stateful objects at runtime. Only your part of the code was ever kind-of pure. It was an illusion, and Hooks just pulled back the curtain.
I think of Hooks as more like a DSL for declaring externalities, which just happens to take the form of a series of function calls. They're clunky for building complex memoized value-graphs [gazes longingly at MobX], and complex useEffect behaviors can get really hard to follow real quick. But for building average web apps - where 90% of the time you're either pulling in standard externalities or defining little pieces of primitive state - they make things really ergonomic. They also enable some fancy optimizations and scheduling on the React side, from what I understand. Overall I think they were the right move for a for-the-masses UI framework.
- bern4444 5y ago> Hooks as more like a DSL for declaring externalities, That's exactly right in my opinion. Hooks are the place to declare stateful and effectful (aka impure) logic. Using a hook is an equivalent signal to using a Future, or an IO in other languages like Scala. Often combinations of useState and useEffect are best written as a custom hook to reduce noise in the containing component. An easy example can be seen in something like const [ name, setName, isValid ] = useValidatedState(state, validationFunction); Seeing that you can easily imagine how it would be implemented: const useValidatedState = <T>(initialState: T, validationFunction: (val: T) => boolean) => { const [state, setState] = useState(initialState); const [isValid, setIsValid] = useState(validationFunction(initialState); useEffect(() => { setIsValid(validationFunction(state)) } [state]); return [state, setState, isValid]; }; Almost always if there's a useState that has an associated useEffect, it should be turned into its own custom hook.
- city41 5y agoThey also eliminate subtle bugs that can emerge from `this` being mutable in classes, and they make the React lifecycle more intuitive. Rather than thinking about whether the component did mount, will mount or will unmount, you just associate side effects with certain states. Dan Abramov has a nice write up on the pitfalls of mutable this: https://overreacted.io/how-are-function-components-different-from-classes/ https://overreacted.io/how-are-function-components-different... With all that said, I would still say I'm not really a fan of hooks. I more see them as a necessary evil than a great feature. I try to use them as minimally as possible.
- brundolf 5y agoWorth noting that mutable-this can be made to work by using something like MobX. It’s not a fundamental problem, just one that React declined to solve directly, which I can’t totally blame them for.