That’s the thing though - hooks aren’t JS. They don’t allow for control flow. Hooks are a language that superficially looks like JS. I’m with you on not inventing new languages, and I wish that React didn’t step so far off that path itself…
This is so silly. Hooks are literally hooks into a scheduling algorithm you are at the mercy of. That scheduling algorithm is pure JS. Of course you don't have classical control flow in someone else's scheduler.
The key users are referring to when talking about "JS vs magic" is that React is just constructing objects and invoking functions, with known semantics, whereas Solid and Svelte are auto-magic-reactive systems without clear semantics rising from the choice to do even more things in their internal black boxes than React, such as never re-rendering components, dark compiler magic on syntax that doesn't naturally map to a JS tree, and other such things
But hooks need to be named "useX" and have restrictions on where to be called (that a program detects). While they are of js clearly they are not "normal" js functions either.
While I use hooks without problem, I also feel like it is an invented mini-language with a lot of extra quirks. Maybe the problem is js does not map elegantly to some of these functional concepts without a good type system.
Hooks don’t actually need to be named “useX”. That’s the convention, and the React team provides a lint rule that enforces it, but you can name your hooks whatever you want and it’ll work fine.
I’m not what sure what you mean by not “normal” JS functions, though? They’re an API provided by a framework, and — like all APIs — they have specific constraints that govern how they’re used.
Absolutely correct. I stand corrected. There is also a lint rule (the program I was refering to) to check that hooks are not called in some wrong places IIRC. Those lint rules are the default for create react app.
To each their own. Although I use react and hooks, for my taste the hooks api is not very clean. All these are implicit not explicit and without linting they can easily result in runtime errors. But maybe I am spoiled by Elm ;)
This is because hooks are just next() calls on an iterator. Is it magic and entirely because the devs thought it was more beautiful than having to pass a key like state = useState("state", 0)? Absolutely. Does it transcend JS, no.
> have restrictions on where to be called (that a program detects)
Yes, it is strange that they opted for this implicit approach, but this is the nature of interacting with a scheduling algorithm in real-time; it is with limitations
I agree they are clearly not unrestricted free-use JS, but they aren't a custom DSL hydrated by compile-time craziness, they are hooks into a scheduling algorithm to help you maintain consistent state in a giant tree. I'm not sure how that is ever going to be free. Perhaps a better type system can help but this is fundamentally complex
The code in React executing components relies on hooks running in a consistent order each time the component runs, but the existence of a runtime context that has expectations about side effects (and hooks are side effects) doesn't make it “not javascript”.
Hooks are functions, and they are executed in the order called from within the component, which is itself a function, just like any other functions calls from within another function.
(The mechanism tracking calls to them and deciding whether the function passed to the hook needs to be called requires them to be called in the same order each time the component is executed; if they were called in order of definition rather than normal execution order this would be true by definition; the whole reason for the rule about not using flow control around them is that they are functions executed in normal flow order.)
It only matters that the order not change dynamically between renders. This probably could have been avoided if react required a unique key per hook, but I think for brevity it's a decent trade-off.
For the life of me, I can't understand why they didn't go the route of "add an id to your hook." It would solve one of the two big gripes people have with hooks.
ids would be stuttering (especially for things like useMemo/useState), add a different source of error, and—if the goal was to make hooks compatible with flow control—probably create new categories of bugs that would be harder to catch in a linter or even with runtime checks like the existing “number of hooks cllaed changed” one.
Adding visual noise to enable subtle bugs may not be a win.
"Just" is not really fair here, they're a window into global variables. Global state is awful to deal with but a necessity in the real world, so having some sort of constrained global state is something we're always trying to solve in new ways, singletons, monads, etc. Here we have hooks, which is an interesting experiment but something I personally would have played with in some new framework rather than dropping into the most popular and mainstream one.
Depends on what you mean by global state. You don't have access to a single pool of global variables. You only have access to what you put there and what you've been given.