As requested by @jbucaran in the slack channel, I am posting a request for fragmented state. The idea would be to map the namespace of actions to the namespace of state, such that the action actions.text.changeText, instead of receiving the global state, would receive state.text as _state_. Or actions.robots.robotarm.crush would receive actions.robots.robotarm as _state_.
Below would be a simple example:
app({
state: {
counterActions: {
counter: 0
}
},
view: (state, actions) => <h1 onclick={actions.counterActions.click}>{state.textActions.counter}</h1>,
actions: {
counterActions: {
click: (state) => {
state.counter++;
return state;
}
}
}
})
The benefit of this would be:
counters and robots are completely self contained:import {counterState, counterActions} from 'counters';
import {robotState, robotActions} from 'robots';
import view from './views/robotCounter';
app({
state: {
counters: counterState,
robots: robotState
},
actions: {
counters: counterActions,
robots: robotActions
},
view: view
});
I think this would be extremely simple to implement: simply modify _app.js:init()_ around line 37, to return a property instead of the entire state. I would be happy to make the change myself, if people think it is a good idea.
Thanks for your time. Please let me know if there is anything that is unclear, or you have any other questions.
Hi @rexrhino and thanks. If you think this is easy to implement, I'd gladly review your PR.
This concept of fragmented state seems the same as the thing I have called "scoped actions", and it has had a little bit of discussion here: https://github.com/hyperapp/hyperapp/issues/210
Not making a point for or against - just tying together the discussions.
We still need a way to skip this. I'm really sure that the stuff I'm doing at @attach-live would be completely broken if there is no opt-out.
I really like the idea of not requiring extra configuration to have them mapped over, just having everything work out of the box and be ready to go. One of the things I really like about hyperapp is just how clean it is and how little boilerplate everything requires.
What if instead of mapping everything in state to the corresponding namespace in actions, it mapped something like state.actions.robots to actions.robots.attack, actions.robots.run, etc? Or maybe state._actions.robots if "actions" is too generic? So people who want the mapping just throw all their states in the "actions" section, and people who don't want it automatically mapped can put things directly in the root?
For example:
app({
state: {
actions: {
counterActions: {
counter: 0
}
}
},
view: (state, actions) => <h1 onclick={actions.counterActions.click}>{state.textActions.counter}</h1>,
actions: {
counterActions: {
click: (state) => {
state.counter++;
return state;
}
}
}
})
@rexrhino I can live with (and would probably utilize) something like that.
@rexrhino I think it might make more sense to do it the other way around though. That way actions would still be able to access the whole state if they're in a sub-category and actions would just get a POV on the state, not the other way around, so the state stays clean and you can have some actions that work with the full state and some that work with a subset.
@dodekeract: Yeah, I agree, I think it would be better to be opt-in for global state, and by default have a state that matches the namespace. So, if you wanted actions to have access to the global state, you would put them actions.global, otherwise they would go in actions and be mapped to state.
My goal is to create the PR this Wednesday night, so if this idea seems bad, or there are problems that need to be resolved, or people just aren't interested - let me know.
Does this go against the Elm way? Just wondering 馃槃
Is this a way to appease the law of demeter (slight edit)? 馃
@selfup Yes, att least to allow for it. At the moment, every action needs to know about the structure of the entire state object in order to work, making any effort to separate concerns into different modules kind of pointless.
I see it more as an improvement on the Elm way, as going against it :)
(Btw I think you meant to say "Law of Demeter" 馃槈 )
@zaceno yes my phone auto corrected 馃槀
Thanks for the insights
The benefit of functional programming here is that it can easily be done in userspace.
PoC without async support:
https://codepen.io/naugtur/pen/zzNXJL
Totally optional fragmentation/nesting to any depth.
Closing in favor of #238
Most helpful comment
@selfup Yes, att least to allow for it. At the moment, every action needs to know about the structure of the entire state object in order to work, making any effort to separate concerns into different modules kind of pointless.
I see it more as an improvement on the Elm way, as going against it :)
(Btw I think you meant to say "Law of Demeter" 馃槈 )