4 ms·
Looking at the design, it's clear that the team is trying really hard to make functions look and work like classes look. Variable declarations at the top, follo
by politician 8y ago
Looking at the design, it's clear that the team is trying really hard to make functions look and work like classes look. Variable declarations at the top, followed by helper methods, followed by lifecycle methods. Given that classes are themselves sugar to make prototypes palatable to a broad range of developers, it's certainly a tough design task; I'm not convinced that reliance on call-index is wrong per se, but it is magical (and magic in JavaScript is obnoxious).
That said, the presentation of the third and forth flaws seem a bit weak. useState accepts a key as the first parameter, but in both of the composite functions that input parameter disappears. That looks like a refactoring error.
From a design standpoint, if `useState(symbol)` is acceptable (and I'm not saying it is), then `useWindowWith(symbol)` would likewise be acceptable in that it's not adding any more requirements to the interface than the vanilla version.
Proper bookkeeping of symbols resolves the issues here. However, if the design objective is to reduce the effort on the developer to do their own bookkeeping, then call-order indexing does make sense.
(Not to mention that Symbols are not supported by IE11 which remains an important target for bigger companies.)
I'm not sure there's a good way out. When you look at solutions like Protocol Buffers, they just bite the bullet and require the developer to supply the indexing. If JavaScript had something like Go's iota, then you could imagine using an enumeration to supply the indexing without requiring everyone to type 1,2,3,4... etc. But it doesn't so, that's wishful thinking. Nevertheless, the react codebase itself does contain a giant list of assignments of Symbol() || number to constants, so it's a pattern you're already aware of.
A tough nut to crack.
- danabramov 8y ago>From a design standpoint, if `useState(symbol)` is acceptable (and I'm not saying it is), then `useWindowWith(symbol)` would likewise be acceptable in that it's not adding any more requirements to the interface than the vanilla version. I think you're missing that `useWindowWidth()` could have more than one `useState()` and thus you'd need to somehow compose Symbols. Which is what the next section is about.
- danabramov 8y agoIn particular, I would suggest to take the `useSubscription` example from "diamond problem" section and try to convert that whole snippet. You'll see where it falls apart.
- politician 8y agoI must be missing something because this didn't fall apart when I refactored it to work with a `useState(symbol, value)` interface. I'm not saying this is a good or ideal solution, indeed if the useWindowWidth hooks were to both useState and also useSubscription, then multiple keys would have to be injected -- it would work correctly, but the interface would have the AMD feel that perhaps is undesirable (per flaw #8). https://gist.github.com/politician/5f03c169a4119a63abb785b1c1249656 https://gist.github.com/politician/5f03c169a4119a63abb785b1c... EDIT: I still think it's a hard design problem and the concerns in flaw #8 are _very real_ to a broad range of developers. When you're just trying to get it done, proper bookkeeping of Symbols and injecting them into hooks composed of other hooks might cross the line. It's a shame that relying on call-order indexing is the solution because it's magical. But at the end of the day, engineering is about trade-offs. Time will tell whether deeply nested composition of automatically-managed hooks was a good feature to expose.
- WorldMaker 8y ago> It's a shame that relying on call-order indexing is the solution because it's magical. I've been thinking about this a lot since Hooks were introduced, and I'm increasingly of the opinion that it isn't that magical. Order of operations is incredibly important in the functions we write, especially in a language like JS that makes no effort for strict "pure" side-effect free functions. The order of a console.log or a return versus an increment matters in JS. We write a lot of procedural code in JS where order matters (a lot) already. In that matter, Hooks can just melt into the "procedural" background of JS. That said, I still feel like I want a better solution than "lint errors" for things like accidental branches of a Hook. I don't have any more of a proposal for how that would work or what that would mean than the article here, though, unfortunately.