logoalt Hacker News

fleabitdevlast Sunday at 11:50 PM0 repliesview on HN

Reactivity works by replaying code when its inputs have changed. Events can make this very expensive and impractical, because to properly replay event-driven code, you'd need to replay every event it's ever received.

When we replace an event stream with an observable variable, it's like a performance optimisation: "you can ignore all of the events which came before; here's an accumulated value which summarises the entire event stream". For example, a mouse movement event listener can often be reduced to an "is hovered" flag.

Serialising program state to plain data isn't always easy or convenient, but it's flexible enough. Reducing all events to state almost solves the problem of impure inputs to reactive functions.

Unfortunately, reactive functions usually have impure outputs, not just impure inputs. UI components might need to play a sound, write to a file, start an animation, perform an HTTP request, or notify a parent component that the "close" button has been clicked. It's really difficult to produce instantaneous side effects if you don't have instantaneous inputs to build on.

I can't see an obvious solution, but until we come up with one, reactive UI toolkits will continue to be ill-formed. For example, a React component <ClickCounter mouseButton> would be broken by default: clicks are delivered by events, so they're invisible to React, so the component will display an incorrect click count when the mouseButton prop changes.