6 ms·
As someone who's new to react, and basically started with hooks: am I missing something? The old class based code looks so much better than the hooks magic. Is
by wheybags 5y ago
As someone who's new to react, and basically started with hooks: am I missing something? The old class based code looks so much better than the hooks magic. Is this just js people hating OO or is there something deeper?
- jolux 5y agoFor one thing they currently plan to maintain classes indefinitely, so if you really wanted to get started with classes you can just do that, and learn hooks later. That said, the React docs are pretty clear about the motivation for hooks and I think that is a good place to start: https://reactjs.org/docs/hooks-intro.html#motivation https://reactjs.org/docs/hooks-intro.html#motivation. After that, this post explains roughly how hooks actually work (in a simplified way), and why they're a more natural fit for what's happening under the hood: https://www.netlify.com/blog/2019/03/11/deep-dive-how-do-react-hooks-really-work/ https://www.netlify.com/blog/2019/03/11/deep-dive-how-do-rea...
- recursive 5y ago> That said, the React docs are pretty clear about the motivation for hooks and I think that is a good place to start: https://reactjs.org/docs/hooks-intro.html#motivation https://reactjs.org/docs/hooks-intro.html#motivation. I've read this a number of times, and none of the point make sense to me. > It’s hard to reuse stateful logic between components Is there some reason you can't use a `get(key)` and `set(key,value)` between class components. I don't really grok react, despite trying, so maybe there's a reason that doesn't work. > Complex components become hard to understand I don't understand what the hard part is supposed to be here. If you have a method that's dealing with too many concerns, you can just add methods, and then call those. > Classes confuse both people and machines `this` is pretty confusing in javascript, but yet that's the language react is targeting. And it's no less confusing in prototype-based objects. And after having tried to learn both hooks and `this`, it certainly doesn't seem like hooks are conceptually easier than `this`. Probably my fundamental problem with hooks is trying to understand which state goes with which component-function invocation. It just seems like dark magic that usually works. I've tried to read the implementation to figure it out. It seems to depend on the famous DOM diff feature. It was about at that point that I lost the plot. So, I know I'm an outlier, but class-based components just make sense to me. They can be complex, but fundamentally comprehensible. Function components seem like a fake simplicity that's masking a complexity that I've yet to figure out.
- srcreigh 5y ago> Is there some reason you can't use a `get(key)` and `set(key,value)` between class components. I don't really grok react, despite trying, so maybe there's a reason that doesn't work. You can and the hooks way is better. The class based components way is to wrap component in a HOC. The common state is stored in the HOC. The HOC passes the state to the component via props. This can include functions, so maybe your component can call `this.props.reloadApi()`, which changes HOC state, which results in new props sent to your component. The hooks way is described here. [0] What's wrong with Higher-Order Components? One answer is that it's weird to call something a "component" which doesn't render any UI. In other words, why is an interface to access remote data a "component"? Another answer is that HOCs break the diff algorithm without special care see. [1] [0]: https://reactjs.org/docs/hooks-custom.html https://reactjs.org/docs/hooks-custom.html [1]: https://reactjs.org/docs/higher-order-components.html#dont-use-hocs-inside-the-render-method https://reactjs.org/docs/higher-order-components.html#dont-u...
- recursive 5y agoBut why use a HOC? `useState` is a global function. I don't see a problem using some kind of static global state factory thing. Likewise, you could just call set() and get() without any of the fancy stuff. Maybe I'll try implementing this to show what I mean/learn why it wouldn't work.
- fastball 5y agoAre you talking about having some global store that you're calling `set()` and `get()` against? If yes, the reason you can't just do that is because if that is done naively then components using `get()` won't know that they need to re-render when a `set()` is called somewhere else. Not done naively and you do have global stores built for this, like Redux or MobX, which handle this gracefully and (at this point) use hooks under the hood and in the dev-facing API to accomplish this. Tbh this is also now built-in to React with the `useContext()` hook, which allows you to do the same. `useState()` should really only be used for local-to-a-component level state (though technically you can obviously pass down the state/setter to any child components, but given the above I find it's frequently better to `useContext()`).
- acemarke 5y agoThe post "Why React Hooks?" helps explain the historical context and reason for their creation: https://ui.dev/why-react-hooks/ https://ui.dev/why-react-hooks/ I also discussed some of the tradeoffs in a conference talk and blog post: https://blog.isquaredsoftware.com/2019/07/blogged-answers-thoughts-on-hooks/ https://blog.isquaredsoftware.com/2019/07/blogged-answers-th... https://blog.isquaredsoftware.com/2019/09/presentation-hooks-hocs-tradeoffs/ https://blog.isquaredsoftware.com/2019/09/presentation-hooks...
- afavour 5y agoIt’s a better representation of what’s going on underneath but FWIW I agree with you, there are very few instances where I find hooks code that’s as readable as class-based code. I know I’m not typical at all but hooks kind of marked the point where I lost interest in keeping up with the changes in React. I’m lucky that my job doesn’t require me to and I’ve had a great time exploring options like Vue and Svelte. Svelte in particular feels like it takes the opposite approach to hooks-based React: rather than force you to think about the way React is processing things it lets you write code the way you think about things and transpiles it into working JS. Beyond “everyone uses it” I can find few reasons to prefer React these days.
- stack_framer 5y agoThis is exactly how I feel. I remember watching the hooks announcement video and being surprised that classes, 'this', and the lifecycle methods were considered so ... problematic. It seemed like hooks were solving problems that, for me at least, were totally and completely non-existent. It didn't help that my first foray into hooks was trying to build a simple clock with `setInterval`: https://overreacted.io/making-setinterval-declarative-with-react-hooks/ https://overreacted.io/making-setinterval-declarative-with-r... I really need to give Svelte a try.
- sibeliuss 5y agoWhen React introduced hooks they also massively expanded the library's API, so there's a complexity cost to that. While I love working with hooks and do so daily, I definitely felt some remorse for those now having to figure out when and how to use memoization, dependency arrays, useCallback, etc, etc etc. React in its first formulation was utterly simple and beautiful. In defense of hooks however, it's good to keep in mind that now you can do a lot more than you could, and being able to share business logic so easily across an application is an elegant abstraction.
- srcreigh 5y agoIf you want to see really ugly code, read the docs about Higher Order Components [0]. Hooks are better for building component abstractions than HOCs. Code which can hook into mount/unmount, can trigger re-renders via state updates, etc. Also, dependency arrays in useEffect and useCallback are better than this kinda stuff in shouldComponentUpdate lifecycle method: if (prevProps.commentId !== this.props.commentId) { return true; } return false; [0]: https://reactjs.org/docs/higher-order-components.html https://reactjs.org/docs/higher-order-components.html
- debaserab2 5y agoI find dependency arrays to be neither intuitive or easy to debug. When you're missing a parameter or use the wrong one React can emit some pretty weird side effects that are hard to track down back to the dependency array. I generally like shaping my components as functions first and use hooks because I have to in order to do this but definitely not because I find them easier to understand than component lifecycle methods (even if they may be less verbose). To me, hooks are the ugly part, writing component as a single function is the part that makes it worth it.
- jitl 5y agoDo you use the exhaustive-hooks ESLint rule? I think without it hooks are unusable in a team setting.
- brundolf 5y agoIt helps a lot, but it has gaps, because it reasons about syntax and not values. A complete solution is intractable without integrating this stuff at a language/type-system level (and I don't mean TypeScript; TypeScript can't represent hooks' relationships either).
- nightpool 5y agoThe general advice is to write your hooks without dependency arrays first, and then only add dependency arrays once you know what your hook body looks like. I find that that generally makes them much easier to debug. Also, yes, the exhaustive-hooks ESlint rule is a life-saver.
- jitl 5y agoThe hooks approach is all about making the UI more incremental. I have an easier time reducing the work the computer has to do by using hooks like useMemo and useEffect compared to custom prop diffing. For example, building complex query forms over large amounts of in-memory data that do minimal async requests and re-computations when props change is much easier with hooks. useEffect/useLayoutEffect also makes behavior lifecycle for weird DOM stuff like MutationObserver easier to manage since you don’t need to spread it out in like 6 different lifecycle callbacks. On the other hand, class components have a better developer experience for components that are mostly dumb renderers that bind a lot of event handlers - `private handleFooClick = () = > { … }` is a lot nicer than `const handleFooClick = useCallback(() = > { … }, […])` and you don’t have to worry about ordering between your methods definitions in classes. Declaration ordering between hooks is annoying, but what you get in return is incremental computation. If you don’t need that stuff, sure - use a class! I do find more and more frequently as I’m working with class components thinking “dang, this would be much easier with hooks”, especially for tricky problems. I don’t find the opposite to be true in hook components.
- vidyesh 5y agoIt is weird, isn't it? I like class components but with complex functionality or rather a bigger codebase functional components are much easier to work with and adding hooks later on is much easier than updating class components. But for some reason, picking someone else's class component and working on it feels much easier than someone's functional component. I 100% agree with the last statement, most problems feel easier to write with hooks than with class components.
- pcl 5y agoThe sense I get is that the original React model has some pretty significant complexities, especially around shouldRender and prop / state analysis, and hooks present a big improvement on that. I don’t think that the class-vs-function divide is the fundamental reason for the problems with the old model or the improvements with the new model. Rather, I think the learnings from the original approach informed the system and resulted in a step forward. I find that once I need to manage a nontrivial amount of state, the functional model really feels wrong — useContext, I’m looking at you! And I wouldn’t be surprised if we end up with another turn of the crank that introduces a class-based (or prototype-based) approach with a better set of abstractions at some point down the line.
- posix86 5y agoBut it's not really OO, it's some ugly mix with rules: * don't put side-effect initialization code into the constructor * use state to render your components * don't set state directly, use setState, _unless_ in the constructor * if you want to use stores, declare a static field You don't inherit classes, as there are many special methods, and overwriting them would mean calling super - before your method body? After? During? Class based components only pay off if you have truly large and complex components, and that's an antipattern in react anyway. Hooks are concise, and super clear if you keep it simple (there are also additional rules not enforced by the compiler, like putting all side-effectful code into useEffect, but still).