Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I think `view = fn(state)` is mostly right but how it is implemented is wrong. If we look at react, everything is nice and declarative until you register event handlers, at which point you enter imperative land to hand manipulate state.

I think what is more accurate is: `view = fn(event-stream)`. Events include but not limited to:

- User events

- Prop change events

- Local state change events

- Global state change events

When we switch the paradigm to be about event streams, all of a sudden there is no bifurcation between prop, local state, global state, and user events -- it is all treated the exact same.



The purpose of `view = fn(state)` is to protect you from O(n*m) complexity scaling if you handle each event in isolation.

For any given part of your UI, you'll have n events to handle ("UI started up for the first time", "x changed", "y changed", "checkbox toggled", "undo", "redo", "file loaded"), and m invariants to uphold ("while the checkbox is checked, the user cannot edit y", "while x is less than y, the UI should display a warning", "this label displays the current value of y as a localised string"). If you try to manually maintain each invariant when handling each event, you'll find it works for simple cases, but it falls apart for larger values of n and m.


This sounds like `state = reduce(state, event)` and `view = fn(state)` where the view has UI handlers that dispatch events rather than mutating anything.

Elm is probably the simplest example of this paradigm top-to-bottom, but you can wire up something pretty simple in vanilla React with just useReducer and useContext.


I like to think of it as `view, effects = fn(state, events)`, where effects are any subsequent events or instructions that come out of a state change. I think of it very close to how you're outlining it here, though, and when I'm thinking of effects I'm generally also thinking of it as a set of things that can fit into an event stream like you're outlining.


All that you've done there is allow different event-streams resulting in the same state to be represented in different ways. Which is just bad design.

Technically you could also have the even worse situation of equal event-streams leading to different states, but being represented the same way. If you think that won't happen you don't understand concurrency well enough.

If you want to deal with event streams I'd start from the basic state machine:

    state :: event -> state




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: