Scope mixins
See original GitHub issueIntroduction
Why mixin needs to specify its namespace in state and actions? The main purpose of mixin with state or actions will be almost always adding these two props under key with name of mixin (because naturally we want to avoid namespace pollution) so what if we scope state and actions in mixin automatically?
Actual behavior
Now it’s working like this: counter | app.
Proposal
I propose that we change a little bit behavior of mixins. It would give more sense if we automatically scope mixin’s state and actions so mixin doesn’t need to use own name inside of itself. Change will be needed in the core of HyperApp where we must store state and actions of every mixin under mixin name. And mixin’s actions must be initialized with scoped state and actions.
But if we need global addition of mixin’s state/actions to app (to first level without storing under mixin name) then we can inform app about globals for example by nesting under global
prop in mixin (example) which will return mixin structure under “mixin.global.state” or “mixin.global.actions” and in HyperApp will be verification if mixin contains “global” and if so then it will store it immediately to first level of state or actions.
Proposed behavior
After this change would be possible to write mixins like this: counter | app. You can switch between “master” (actual behavior) and “scope” (with proposal) branch for comparison.
For this purpose it would be better to change mixins
prop from array to object (key = mixin name) because then we can use mixin’s name as a namespace for storing mixin’s state (state.mixinName
) and actions (actions.mixinName
).
And another advantage would be optional change of mixin’s name so for example if you need use “router” as a key in your business logic and at the same time you need package Router
then you can include this package under different name in mixins (e.g. mixins: { _router }
).
Summarize
- Change prop
mixins
to object. - Scope automatically
state
andactions
in mixin. - Add some signal for “global” state and actions so you can avoid automatic storing under mixin’s name
P.S.: I’m working on this experiment so later I can send working example.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:31 (23 by maintainers)
Hyperapp 0.15.0 solves this in the core with modules. 👍
Notes
Here is what we are trying to achieve in easy to understand pseudo-code.
This is the app.
Let’s define mixin A.
And mixin B.
As you can see mixins A and B state and actions seem to be isolated from the global state/actions. In fact, the state either mixin action receives is a fragment of the global state.
This, of course, is not how mixins work at the moment. The proposal is to make them work that way.
So, for completion, here is how the global state and actions are updated behind the scenes during init.
For convenience, let’s call the global state/actions objects STATE and ACTIONS.
Another way to think about this is namespaces.
But this is much more than just a namespace. The real difficulty is to correctly call those actions passing the piece of the global state that corresponds to that specific namespace/scope.
Not every app uses a mixins, so all of this stuff is only relevant if you are using mixins.
I still need to fully grasp all the implications, but basically this allows you to create mixins that don’t need to know how to grab their state/actions from the global state.
It’s also limiting because then there is no way for a mixin to merge something in the top level (probably not a good idea anyway).
This also makes actions extremely convenient to work with in deeply scoped mixins.
Notice how mixins can be nested.
My worry is that this looks a lot like stateful components.
But it isn’t. This is definitely a single state tree.
/cc @zaceno @MatejMazur