5 ms·
Are hooks being accepted as a good design by the community? It seems to me that the lack of a parameter explicitly indicating the component and the reliance on
by devit 8y ago
Are hooks being accepted as a good design by the community?
It seems to me that the lack of a parameter explicitly indicating the component and the reliance on hook ordering to match them across calls of the component function make them a bad design, but I might very well wrong and would be happy to be convinced otherwise.
- Lazare 8y agoMy impression is the community is mostly accepting, but some are taking a wait and see attitude until they can see it in production. I don't think there's a lot of concern about hook ordering; it's hard to see that being a serious issue in practice. And it has some significant advantages over existing alternatives.
- emerongi 8y agoMaybe it won't be an issue. However, it does go against regular advice of being explicit over magical. Depending on call order is something that immediately pops out as fishy. As always, programming is about trade-offs and the React team is claiming this trade-off is worth it.
- ricardobeat 8y agoApparently React's internals have been doing similar order-based magic for a while already.
- Vinnl 8y agoThat's also the reason why you have to make sure you're passing an update function to `setState` sometimes.
- jontro 8y agoThat's not why you have to do it, it's because the state can be updated asynchronously. It's only applicable when you try to update the state based on previous state or props values.
- joesb 8y agoIf you have a stack machine, when you write a function like this. function foo() { let x = 1; let y = 2; x + y; } Your code already depends on ordering. x is on the stack first. y is on the stack second. You don't randomly rewrite this two lines of code on every invocation of foo. `let x = 1` and `let [x] = useState(1)` is the exact same thing.
- deleted 8y ago[deleted]
- fold_left 8y agoThis talk introducing hooks explains it well: https://youtu.be/V-QO-KO90iQ https://youtu.be/V-QO-KO90iQ:
- sudhirj 8y agoI'm using them on my current app, and have no intention of going back to classes. > lack of a parameter explicitly indicating the component That's sort of the whole point. That you can write general purpose side effect functions that don't need to care about which component they're being used in. It's super easy to have a toolkit small unit testable functions that do the pretty much all the work in the application. Far easier to work with than inheritance, mixins or traits. Easier than composition, even, because this is just calling functions. If you're familiar with using Underscore or lodash, this model will feel very intuitive. > reliance on hook ordering This is a red herring, because we're only talking about execution ordering when the code runs. It doesn't actually matter what order I write any code in, only that when the code runs the order doesn't change between two render frames. This is as simple as don't have conditionals outside the hooks, have them inside. If you think of hooks as accessing the state register by the index of their first access, it works well as a rule of thumb. The real problem is the impedance mismatch that the line above causes - you need to remember that hooks access the state register by order of their first appearance, not by identity. So if hook no. 3 doesn't execute on the second render for some reason, hook no. 4 will see hook no. 3's data. This goes very contrary to JS or any other programming language / paradigm I know. It also has repercussions (https://overreacted.io/making-setinterval-declarative-with-react-hooks/ https://overreacted.io/making-setinterval-declarative-with-r...) that are unintuitive, because the identity of the functions you pass into the hooks is lost as well, so you need to put them into the call-positional state register via a ref. To be honest, I haven't hit that edge case yet, and it's easily handled once you understand the system for what it is. It is very un-intuitive to program this way, but it's not a problem most of the time. Just remember that the identity of the state of any hook is represented only by its sequence number of execution during the first render, and you can figure out the remaining gotchas from that.
- WorldMaker 8y agoIt shouldn't feel that unintuitive, it's not actually that uncommon in JS and/or any other programming language that the order of calls matter. It's basically a fundamental quirk of all (side effect full) imperative code. It's the languages where call order doesn't matter than are much more rare, and are more generally considered unintuitive (for instance, Haskell pure functions). The cannot be called in conditionals and/or loops need is certainly more rare, but it's also not necessarily an exotic thing: so much of debugging and performance work in the average imperative language is often finding things called conditionally or in loops that shouldn't be and moving them up/out. Some things like setInterval or certain types of awaiting large expensive computations you almost wish you had lint errors in place to forbid them in loops (or even sometimes to forbid them from conditionals in cases where they don't happen cause subtle bugs). I don't think this is contrary to JS at all. It's different and may take some time getting used to, but "call order matters" isn't unusual for JS (especially in the world of DOM manipulation).
- dfabulich 8y agoThis post by React dev lead Dan Abramov goes deep into this question (much more detail than is available in the React Hooks FAQ or the ReactConf talks). https://overreacted.io/why-do-hooks-rely-on-call-order/ https://overreacted.io/why-do-hooks-rely-on-call-order/ tl;dr: The primary design goal of hooks is to support the creation of custom hooks, which can eliminate the need for higher-order components in many cases. An ideal alternative implementation would support custom hooks, without relying on call ordering, and without requiring a linter to guarantee safety. Unfortunately, there doesn't appear to be an approach that satisfies all of these requirements. Depending on call order is apparently the least-bad approach to hooks.
- danabramov 8y agoI’m not a dev lead — if anyone, Sebastian (sebmarkbage) is. I just enjoy turning his sentences into blog posts. :-)
- joesb 8y agoThink of series of `useXXX` as declarations, not function calls, then everything will make sense to you. The declaration parts are always static and in the exact same order for the same component. When you see a state less function ToggleButton = () => { const [flag, setFlag] useState(false) const [count, setCount] useState(1) const useEffect(()=> {....}) return <button onClick={() => setFlag(!flag)>{flag}</button> } View it as a component with two separate sections, behavior declarations and actual rendering: Component ToggleButton // declarations hasState: "flag" setterName: "setFlag" hasState: "count" setterName: "setCount" onEffect() { .... } render() { return <button onClick={() => setFlag(!flag)>{flag}</button> } } Then you will see that reliance on hook ordering being the same is what you always do when you write a declarative code anyway.
- judofyr 8y agoSoo, why couldn't this be implemented as: class ToggleButton extends React.Component { flag = useState(this, true) count = useState(this, 0) other = useEffect(this, () => { ... }) render() { return <button onClick={() => this.flag.set(!this.flag.current)>{this.flag.current}</button> } } Then it's very clear that we have two separate sections: initialization and rendering. There's no longer a hidden state stored somewhere else, but you know that if you have the same `this` then you have the same state.
- danabramov 8y agoBut that’s not how it works. They don’t run during initialization, they run on every render. That’s their whole point and what makes them dynamic. I tried to explain this here: https://overreacted.io/why-do-hooks-rely-on-call-order/#flaw-7-cant-pass-values-between-hooks https://overreacted.io/why-do-hooks-rely-on-call-order/#flaw...
- ncphillips 8y agoThis is such an excellent point. I made a prototype of a class based alternative to hooks, and while I liked some aspects of the API more, it definitely did not take this use case into account!
- skrebbel 8y agoI think time will tell. It's basically the magic vs explicit discussion all over again. Like usually in this discussion, the magic approach is really appealing until it doesn't work, and then the pro-explicit people will go all "told you so" on you. I personally really prefer explicit, having cut my fingers on magic one time too often. Instead, I'll gladly create classes if the thing I'm making has its own state (of any kind). In fact I pretty much disagree with the current trend of wanting to shoehorn everything into this idea of declarative and/or functional programming. Especially in a language like JS, functional programming and some cherry-picked ideas from OO mesh really well together. For example, if you allow me to drift a little, did you know that you can add methods to the prototype of an Immutable.Record? You can even use class syntax! More to the point, if there's one place where OO ideas shine, it's UI components. A lot of OO ideas were particularly designed and developed for UIs. Just like "let" and "const" let me communicate to the reader whether a variable is going to change, I like how in React-land "class" and "function" let me communicate to the reader whether a component has mutable state. Hooks feels like a hack to be able to change the value of a "const" without turning it into a "let". Get over yourself, make it a "let" already. So for me, Hooks is an attempt to throw the baby out with the bath water. I don't experience the problem it's trying to solve. I like classes when they're appropriate. I get the argument that custom hooks allow for easier reuse than higher order components, but I think the difference is marginal; you have to wrap your mind around the exact same complexity. Plus I think higher order components themselves are overused, but that's another story. But! The React people strike me as a rather reasonable bunch. I strongly doubt they're going to move React into a direction where you're forced to make your state (slightly more) implicit. There's too varied a community around React now. I think React with classes and React with hooks can perfectly coexist. Also if my favorite open source React tool adopts hooks and forces me to do the same here and there, then sure I might be grumpy for a few minutes but in the end, well, I'll survive.
- Vinnl 8y ago> It's basically the magic vs explicit discussion all over again. Like usually in this discussion, the magic approach is really appealing until it doesn't work, and then the pro-explicit people will go all "told you so" on you. Well... Have any "pro-explicit people" gone all "told you so" about all the magic that's going on with setState? I don't think so. I don't think it's a binary magic vs explicit choice. I usually lean towards explicit, but as setState demonstrates, it's possible to find some kind of balance where the benefits of the magic outweigh the downsides, or at least are not that bad of a choice.
- danabramov 8y agoWhile HN wasn’t convinced last time I posted this, here’s a few posts or sections that explain the static call order thing: https://overreacted.io/why-do-hooks-rely-on-call-order/ https://overreacted.io/why-do-hooks-rely-on-call-order/ https://overreacted.io/react-as-a-ui-runtime/#static-use-order https://overreacted.io/react-as-a-ui-runtime/#static-use-ord... https://github.com/reactjs/rfcs/pull/68#issuecomment-439314884 https://github.com/reactjs/rfcs/pull/68#issuecomment-4393148... (Persistent Call Index section) Hope this helps, happy to answer questions. We’ve been using Hooks for several months at FB and haven’t seen confusion caused by the call order reliance. (Note Hooks don’t rely on specific call order but just on it being static between renders. Which is pretty easy to understand and reasonably enforce in practice.)
- k__ 8y agoI found it especially nice that React told me where I was doing it wrong.
- palerdot 8y agoOne thing that looks 'magical' is how does the setWhatever function lets React know that state has changed and has to re-render? Is there any info/writeup on this anywhere?
- FLGMwt 8y agoThe component renders any time the setWhatever function is called, similar to this.setState() in class components. The presumption is anything that you're storing in state is depended on by the component. If it's not, it doesn't make sense to have it in state anyway.
- danabramov 8y agoPretty much the same way as this.setState in a class does. React knows which component is rendering at any point in time — so it knows which component useState() call corresponds to. I think this explanation is quite accessible: https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e https://medium.com/@ryardley/react-hooks-not-magic-just-arra...
- eknkc 8y agoRecently wrote a customer dashboard app and hooks were just introduced. I'm glad I went full in with them. I think they will be the standard going forward.
- tanilama 8y agoHooks future depends on its objective: a replacement or an alternative? I guess even the React team itself doesn't have an answer for this, that is why they are rolling out Hooks relatively cautiously, not forcing it down to the community like what angular does with its 1.x -> 2.0 push, which I consider as a complete disaster that eventually costed it the victory of last framework revolution. My bet will be on the later. Hooks will become a preference, and there will be a mix of hooks/classes in real world application, since rewriting using Hooks only isn't what most people see will bring immediate benefits. The React community at large from my observation doesn't have a huge issue going forward with the current API, despite being grumpy from time to time.