Combine the concept of state and actions into models 🤯
See original GitHub issueEDIT: @Alber70g suggested an even more extreme simplification:
Instead of
app({ model, view }, root)
→app(model, view, root)
, but we can discuss that on another issue.
We did it once and here we go again. Like everything, there are trade-offs involved, not to mention the pain that comes with the churn. There’s also “done is better than perfect”, but Hyperapp is not done yet, and we still have some time before 1.0. I need your help to evaluate if this idea holds or not, and identify possible drawbacks or disadvantages.
The proposal (via @Alber70g) is to combine the concepts of state and actions into a new abstraction: models. A model is a regular object that holds your state props and actions.
The typical counter would look like this:
app({
model: {
count: 0,
down: () => model => ({ count: model.count - 1 }),
up: () => model => ({ count: model.count + 1 })
},
view: model => (
<main>
<h1>{model.count}</h1>
<button onclick={model.down}>–</button>
<button onclick={model.up}>+</button>
</main>
)
})
An application that is wired to state and actions from multiple sources, could look like this:
app({
model: {
A,
B,
C,
D
}
})
Instead of the current:
app({
state: {
A: state.A,
B: state.B,
C: state.C,
D: state.D
},
actions: {
A: actions.A,
B: actions.B,
C: actions.C,
D: actions.D
}
})
And an app that subscribes to external events.
const { tick } = app({
model: {
time: Date.now(),
tick: () => ({ time: Date.now() })
},
view: model => <Clock time={model.time} />
})
setInterval(tick, 1000)
You can see that the app() now returns the wired model
, so you can access not only actions, but also state props.
Now, you can think of models like a “module” that contains your state and actions under the same namespace.
// A counter model
const counter = {
count: 0,
add: n => model => ({ count: model.count + n })
}
app({
model: { counter },
view: ({ counter }) => (
<main>
<h1>{counter.count}</h1>
<button onclick={e => counter.add(1)}>Add</button>
</main>
)
})
Notice how usage of the model inside the view function mirrors how you define the model above.
Pros
- Simplify your code (save bytes!)
- Simplify core (save bytes!)
Cons
- Breaking change
- Complicate saving the state to local storage, as you will have to exclude actions from the model before you save:
saveToStorage(withoutActions(model))
Notes
- No impact on how slices work.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:15
- Comments:66 (50 by maintainers)
I’m glad my proposal found it’s way. I’m also happy that we can move forward. I for one would be unhappy if I’d had to fork this project for this functionality.
Let’s not forget to thank @JorgeBucaran for creating and pulling this project. He’s making sure this project doesn’t go haywire by making it a real challenge to persuade and convince and bring the right arguments to good ideas. Because of him and through this way we will be able to create something truly beautiful!
@okwolf Good point, I totally missed it. What @vdsabev suggested is actually not correct. Not a problem for me though.