Live data from Hacker News

Why Do React Hooks Rely on Call Order?

overreacted.io

11–20 of 115 posts

Re: Why Do React Hooks Rely on Call Order?

#11
post #4

I’m surprised Reagent’s ratoms weren’t an inspiration. They give you a lot of Hooks functionality largely through Clojure’s native atom.

Yep. We've been using what is akin to an apollo-client hook at work for the past ~9 months or so:

    (defn my-component []
      (let [user-data (data/pull! :user "{ user { firstName  } }")]
        (fn []
          (if (:loading @user-data)
            [:div "Loading..."]
            [:div "Hello, "
             (get-in @user-data [:data :user firstName]) "!"])))
I'm a bit surprised this pattern isn't more popular; having side-effectful functions return ratoms in a form-2 component seems almost as flexible as Hooks. It seems that most CLJS people try and keep their views more pure, which I think is honestly to their overall detriment. You miss out on the encapsulation and composition that React is espousing.

That being said, I intend to replace reagent soon with just raw React + a few helpers :P

Re: Why Do React Hooks Rely on Call Order?

#12
post #7

Beg to differ, yes, implicit call order will result in huge clusterfucks. React+Redux is already causing Frankenstein apps (which is not implicitly caused by those frameworks (ok, maybe except redux) but when you throw in react-redux, react-router, redux-thunk, etc. in the mix it just deteriorates quickly). Well the NPM report showed us the trends. Every major fad peaks around 5 years in the making in JS land and the…

What way of structuring frontend prior to the react/redux 'fad' do you think was superior?

That's a loaded question. What about comparing to the current day alternatives and upcoming ones? People have learned from react/redux and are pursuing alternatives.

Re: Why Do React Hooks Rely on Call Order?

#13
post #7

Beg to differ, yes, implicit call order will result in huge clusterfucks. React+Redux is already causing Frankenstein apps (which is not implicitly caused by those frameworks (ok, maybe except redux) but when you throw in react-redux, react-router, redux-thunk, etc. in the mix it just deteriorates quickly). Well the NPM report showed us the trends. Every major fad peaks around 5 years in the making in JS land and the…

What way of structuring frontend prior to the react/redux 'fad' do you think was superior?

Dont think anything was superior but that doesnt mean its perfect. It still amaze me how much time we have to spent(engineer) to get a frontend working. It really should be a completely or semi completely visual process.

Re: Why Do React Hooks Rely on Call Order?

#14

Earlier quoted context omitted.

What way of structuring frontend prior to the react/redux 'fad' do you think was superior?

Dont think anything was superior but that doesnt mean its perfect. It still amaze me how much time we have to spent(engineer) to get a frontend working. It really should be a completely or semi completely visual process.

It's always strange when people act indignant about the fact that engineering a large frontend is difficult, like the world owes it to them for it to be easy. Frontend code is by nature highly repetitive, but each different unit has its own arbitrary tweaks because of the fact that people have to use it. This makes it very hard to abstract.

There are a million visual frontend builders out there, and they are all terrible, because you can never get them to do what you want. They are only usable to build example apps, and if used for anything real, require a huge amount of hacking around which results in code that is worse than what it would have been otherwise.

Re: Why Do React Hooks Rely on Call Order?

#16
post #14

Earlier quoted context omitted.

Dont think anything was superior but that doesnt mean its perfect. It still amaze me how much time we have to spent(engineer) to get a frontend working. It really should be a completely or semi completely visual process.

It's always strange when people act indignant about the fact that engineering a large frontend is difficult, like the world owes it to them for it to be easy. Frontend code is by nature highly repetitive, but each different unit has its own arbitrary tweaks because of the fact that people have to use it. This makes it very hard to abstract. There are a million visual frontend builders out there, and they are all terr…

Yep. Underestimating frontend complexity is how we got into this mess. Say what you will about framework churn, React is the first one where I really feel like it's easy to apply basic coding hygiene (e.g. treating abstraction and composition as first-order concerns).

Re: Why Do React Hooks Rely on Call Order?

#17
post #7

Beg to differ, yes, implicit call order will result in huge clusterfucks. React+Redux is already causing Frankenstein apps (which is not implicitly caused by those frameworks (ok, maybe except redux) but when you throw in react-redux, react-router, redux-thunk, etc. in the mix it just deteriorates quickly). Well the NPM report showed us the trends. Every major fad peaks around 5 years in the making in JS land and the…

On the contrary: Redux's insistence on serializable events and side effect-free reducers makes debugging these pernicious "state update" ordering issues, which exist with or without Redux, a far easier job.

Agreed. I like to tell people that I like Redux's devtools more than I like Redux. There's a payoff for all the boilerplate.

Re: Why Do React Hooks Rely on Call Order?

#18
post #7

Beg to differ, yes, implicit call order will result in huge clusterfucks. React+Redux is already causing Frankenstein apps (which is not implicitly caused by those frameworks (ok, maybe except redux) but when you throw in react-redux, react-router, redux-thunk, etc. in the mix it just deteriorates quickly). Well the NPM report showed us the trends. Every major fad peaks around 5 years in the making in JS land and the…

When we deal with state full objects (classes instances/ database objects/ in memory caches) -- we have to segregate the operations on those objects as:

( 1 ) Operation can be applied multiple times -- result will not change (idempotant op) -- eg delete, select

( 2 ) Operation order is important (eg balance cannot increment before payment is processed )

( 3 ) operation order is not important, or ordering conflicts can be mitigated by the solution/underlying platform completely.

So what React team has realized, is that updating a state variable ( a change operation), often falls into ( 2 ).

As react getting more and more use, it tries to find more and more areas to optimize. Which is good.

In both time and ram-space dimensions...

For the React's run-time system, to perform global optimizations, it is really important to know what order the developer had implied in his/her design for case ( 2 ).

Very similar, to what an optmizing compiler, would like to know about a flow of calls/etc.

this is very difficult to do for a user level application in JS.

Without some help from the developer using the library, those optimizations cannot be done, or they will cause user's state to get corrupted.

Their solution is to keep the existing machinery as is, but allow a user to 'tell' the framework about the state variables a bit more than usual.

To me this this a fair tradeoff/ask.

So I will have to learn a bit more, and may be even restructure my code, to let React (and React Native) to do better global optimizations....

Why not ?!

Most programming languages syntax is poor as specifying the intended order of function invocation or value change rules, as 'compile-time' directive. (well, I at least, do not know of any language that let's me do that -- so I resort to forcing some order though function arguments and return type, so that a call to nxt function, must have a certain type provided by a return of a previous function...

I think explicit state management, is absolutely the correct problem to tackle. it is difficult and error prone.

It is not fair, in my view, to judge React added complexity in this area, as 'deterioration'.

Ideally these types of things should have been solved by the compilers .. but javascript (and browser) ecosystem is probably 10-15 years away from even thinking about this.

Re: Why Do React Hooks Rely on Call Order?

#19

(I edited the post title to include “React” before the “Hooks” to disambiguate. Might be worth editing the submission too!) Hope you’ll enjoy reading it.

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.

Re: Why Do React Hooks Rely on Call Order?

#20
post #7

Beg to differ, yes, implicit call order will result in huge clusterfucks. React+Redux is already causing Frankenstein apps (which is not implicitly caused by those frameworks (ok, maybe except redux) but when you throw in react-redux, react-router, redux-thunk, etc. in the mix it just deteriorates quickly). Well the NPM report showed us the trends. Every major fad peaks around 5 years in the making in JS land and the…

You have to concede though that once someone sets up the call order, it's really unlikely to change unless there are bugs or someone's coming to do some yak-shaving.

People just don't write productive programs where the instruction sequencing at the function level is non-deterministic or chaotic. The UI is already insane enough with CSS and browser differences fighting you every step of the way to make it worse with clever preambles.

Post reply on HN