3 ms·
>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'
by 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.
- politician 8y ago> I still feel like I want a better solution than "lint errors" for things like accidental branches of a Hook. The best I can come up with is Sweet.js (hygenic macros), but can you imagine what outrage that would provoke?
- WorldMaker 8y agoYeah, macros/DSLs might be a bridge too far for a lot of users. I keep trying to figure out if there is a way to push it into a type safety problem in Typescript, at least. A compile error would be preferable to a lint error, even if not everyone uses a typing compiler like Typescript. If there were some way that you could get use* functions to narrow to `never` in any branch or branch-like position, that would be cool. Unfortunately, I can't think of a natural way in the type system to do that that would work in even a plurality of cases. Which drops back to it needing to be a context-sensitive linter rule.
- politician 8y agoYou might be able to use ES6 annotations to mark use* functions such that a bespoke Babel plugin can assert that the the control flow AST only contains functions so annotated in non-branching positions. Basically, lint, but at transpile time.
- WorldMaker 8y agoSimilarly, tslint operates best as a Typescript plugin and so lint rules in Typescript still can happen at transpile time and aren't necessarily that much different in practice from compiler errors. Still bugs me a little that there's not a higher-kinded type or pattern that I can come up with to do it "for real" in the compilation.