add actions

This commit is contained in:
Yanick Champoux 2019-10-22 18:10:45 -04:00
parent 3f6c31a998
commit 31c6060041
6 changed files with 82 additions and 15 deletions

7
Changes Normal file
View File

@ -0,0 +1,7 @@
# Revision history for Updux
0.0.2 2019-10-22
- Add 'actions' in the config.
0.0.1 2019-10-22
- Initial release.

View File

@ -45,6 +45,9 @@ const {
next(action); next(action);
}; };
}, },
actions: {
customAction: ( someArg ) => ({ someProp: someArg }),
},
}); });
@ -104,7 +107,6 @@ const rootUpdux = updux({
todos, statistics todos, statistics
} }
}); });
```
#### mutations #### mutations
@ -187,7 +189,25 @@ updux({
} }
} }
}); });
### actions
Generic action creations are automatically created from the mutations and effects, but you can
also define custom action creator here. The object's values are function that
transform the arguments of the creator to the action's payload.
``` ```
const { actions } = updox({
mutations: {
foo: () => state => state,
}
actions: {
bar: (x,y) => ({x,y})
}
});
actions.foo({ x: 1, y: 2 }); // => { type: foo, payload: { x:1, y:2 } }
actions.bar(1,2); // => { type: bar, payload: { x:1, y:2 } }
## return value ## return value
@ -215,13 +235,19 @@ mutations will be performed first.
### actions ### actions
Action creators for all actions used in the mutations, effects and subdox Action creators for all actions defined or used in the actions, mutations, effects and subduxes
of the updox config. of the updox config.
The action creators have the signature `(payload={},meta={}) => ({type, Non-custom action creators defined in `actions` have the signature `(payload={},meta={}) => ({type,
payload,meta})` (with the extra sugar that if `meta` or `payload` are not payload,meta})` (with the extra sugar that if `meta` or `payload` are not
specified, the key is not present in the produced action). specified, the key is not present in the produced action).
If the same action appears in multiple locations, the precedence order
determining which one will prevail is
actions generated from mutations/effects < non-custom subduxes actions <
custom subduxes actions < custom actions
### middleware ### middleware
A middleware aggregating all the effects defined in the A middleware aggregating all the effects defined in the

View File

@ -19,7 +19,7 @@
"build": "babel src --out-dir dist", "build": "babel src --out-dir dist",
"test": "jest" "test": "jest"
}, },
"version": "0.0.1", "version": "0.1.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/yanick/updux.git" "url": "git+https://github.com/yanick/updux.git"

View File

@ -9,10 +9,18 @@ test( 'actions defined in effects and mutations, multi-level', () => {
}, },
mutations: { bar: () => () => null }, mutations: { bar: () => () => null },
subduxes: { subduxes: {
mysub: updux({ mysub: {
effects: { baz: api => next => action => { }, }, effects: { baz: api => next => action => { }, },
mutations: { quux: () => () => null }, mutations: { quux: () => () => null },
}) actions: {
foo: (limit) => ({limit}),
},
},
myothersub: {
effects: {
foo: () => () => () => {},
},
}
}, },
}); });
@ -21,4 +29,10 @@ test( 'actions defined in effects and mutations, multi-level', () => {
expect( types).toEqual([ 'bar', 'baz', 'foo', 'quux', ]); expect( types).toEqual([ 'bar', 'baz', 'foo', 'quux', ]);
expect( actions.bar() ).toEqual({ type: 'bar' });
expect( actions.bar('xxx') ).toEqual({ type: 'bar', payload: 'xxx' });
expect( actions.bar(undefined,'yyy') ).toEqual({ type: 'bar',meta: 'yyy' });
expect(actions.foo(12)).toEqual({type: 'foo', payload: { limit: 12 }});
}); });

View File

@ -1,20 +1,40 @@
import fp from 'lodash/fp'; import fp from 'lodash/fp';
function actionFor(type) { function actionFor(type) {
return ( (payload = undefined, meta = undefined) => const creator = ( (payload = undefined, meta = undefined) =>
fp.pickBy(v => v !== null)({type, payload, meta}) fp.pickBy(v => v !== undefined)({type, payload, meta})
); );
creator._genericAction = true;
return creator;
} }
export default function buildActions( export default function buildActions(
creators = {},
mutations = {}, mutations = {},
effects = {}, effects = {},
subActions = {}, subActions = [],
) { ) {
return { ...subActions, // priority => generics => generic subs => craft subs => creators
...fp.fromPairs([ ...Object.keys(mutations), ...Object.keys(effects) ]
.map( type => [ type, actionFor(type) ])) const [ crafted, generic ] = fp.partition(
}; ([type,f]) => !f._genericAction
)( fp.flatten( subActions.map( x => Object.entries(x) ) ).filter(
([_,f]) => f
) )
const actions = [
...([ ...Object.keys(mutations), ...Object.keys(effects) ]
.map( type => [ type, actionFor(type) ] )),
...generic,
...crafted,
...Object.entries(creators).map(
([type, payload]) => [type, (...args) => ({ type, payload: payload(...args) })]
),
];
return fp.fromPairs(actions);
} }

View File

@ -17,10 +17,10 @@ export class Updux {
this.actions = buildActions( this.actions = buildActions(
config.actions,
config.mutations, config.mutations,
config.effects, config.effects,
fp.mergeAll( Object.values( this.subduxes ).map( ({ actions }) => Object.values( this.subduxes ).map( ({actions}) => actions ),
actions ) )
) )
this.initial = buildInitial( this.initial = buildInitial(