|
@@ -1,133 +1,6 @@
|
|
-# redux-sac
|
|
|
|
|
|
+# atpath
|
|
|
|
|
|
-## Slice redux objects (reducers, middleware, ...)
|
|
|
|
-
|
|
|
|
-### `subReducer(key, reducer, additionalKey, ...)`
|
|
|
|
-
|
|
|
|
-Creates a wrapper reducer that calls `reducer`
|
|
|
|
-on the sub-state specified by `key`.
|
|
|
|
-Key can go in different formats, see `deepGetOrNil` below.
|
|
|
|
-Rest of the state is left untouched.
|
|
|
|
-
|
|
|
|
-```js
|
|
|
|
-const r = subReducer("persons", personReducer);
|
|
|
|
-
|
|
|
|
-r({persons: ["John", "Jill"], cars: ["Honda"]}, action);
|
|
|
|
-// => {
|
|
|
|
-// persons: personReducer(["John", "Jill"], action),
|
|
|
|
-// cars: ["Honda"]
|
|
|
|
-// }
|
|
|
|
-```
|
|
|
|
-
|
|
|
|
-Respects redux convention that if no change was made,
|
|
|
|
-the identical object should be returned. So in previous case,
|
|
|
|
-if `personReducer` would return the identical array,
|
|
|
|
-`r` would return the state object it was passed in.
|
|
|
|
-
|
|
|
|
-If persons were deeper in hierarchy, it could have been created as
|
|
|
|
-`const r = subReducer("files.persons", personReducer);` for example.
|
|
|
|
-
|
|
|
|
-You may pass additional keys
|
|
|
|
-as addition arguments. In that case, additional parts of state
|
|
|
|
-will be fetched and passed to a sub-reducer:
|
|
|
|
-
|
|
|
|
-```js
|
|
|
|
-const r = subReducer("persons", personReducer, "assets.cars");
|
|
|
|
-
|
|
|
|
-r({persons: ["John", "Jill"], assets: {cars: ["Honda"]}}, action);
|
|
|
|
-// => {
|
|
|
|
-// persons: personReducer(["John", "Jill"], action, ["Honda"]),
|
|
|
|
-// assets: {cars: ["Honda"]}
|
|
|
|
-// }
|
|
|
|
-```
|
|
|
|
-
|
|
|
|
-This technique is mentioned in Redux docs, in "Beyond combineReducers" page.
|
|
|
|
-
|
|
|
|
-### `subMiddleware(key | selectorFn, middleware)`
|
|
|
|
-
|
|
|
|
-Creates a wrapper middleware
|
|
|
|
-on the sub-state specified by `key`
|
|
|
|
-or the selector function `selectorFn`
|
|
|
|
-by decorating `getState` part of the passed arg.
|
|
|
|
-The `key` can have different format, see `deepGetOrNil` below.
|
|
|
|
-Rest of the passed arg is left untouched.
|
|
|
|
-
|
|
|
|
-```js
|
|
|
|
-const r = subMiddleware("persons", ({getState}) => next => action => {
|
|
|
|
- console.log(JSON.stringify(getState()));
|
|
|
|
- return next(action);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-const altR = subMiddleware(state => state.persons, ({getState}) => next => action => {
|
|
|
|
- console.log(JSON.stringify(getState()));
|
|
|
|
- return next(action);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-// use r or altR in creation of store
|
|
|
|
-
|
|
|
|
-store.getState();
|
|
|
|
-// => {persons: ["John", "Jill"], cars: ["Honda"]}
|
|
|
|
-store.dispatch({type: "any"});
|
|
|
|
-// console => ["John","Jill"]
|
|
|
|
-```
|
|
|
|
-
|
|
|
|
-If persons were deeper in hierarchy, it could have been created as
|
|
|
|
-`const r = subMiddleware("files.persons", ...);` for example.
|
|
|
|
-
|
|
|
|
-You can use `subMiddleware` to sub-state anything
|
|
|
|
-getting one parameter in which
|
|
|
|
-one of the properties passed is `getState` function;
|
|
|
|
-it is not special-case for middleware.
|
|
|
|
-For example, it is usable for wrapping `redux-effex` effect function.
|
|
|
|
-
|
|
|
|
-### `subEffex(key | selectorFn, effects)`
|
|
|
|
-
|
|
|
|
-Creates a wrapper around each element
|
|
|
|
-of the effects array
|
|
|
|
-on the sub-state specified by `key`
|
|
|
|
-or by selector function `selectorFn`
|
|
|
|
-by decorating `effect` function with `subMiddleware`
|
|
|
|
-and returns the array of the wrapped effects.
|
|
|
|
-
|
|
|
|
-```js
|
|
|
|
-const effects = [{
|
|
|
|
- action: "foo",
|
|
|
|
- effect: ({getState}) => {
|
|
|
|
- console.log(JSON.stringify(getState()));
|
|
|
|
- }
|
|
|
|
-}];
|
|
|
|
-
|
|
|
|
-const e = subEffex("persons", effects);
|
|
|
|
-const altE = subEffex(state => state.persons, effects);
|
|
|
|
-
|
|
|
|
-// use e or altE in creation of store
|
|
|
|
-
|
|
|
|
-store.getState();
|
|
|
|
-// => {persons: ["John", "Jill"], cars: ["Honda"]}
|
|
|
|
-store.dispatch({type: "foo"});
|
|
|
|
-// console => ["John","Jill"]
|
|
|
|
-```
|
|
|
|
-
|
|
|
|
-## Compose
|
|
|
|
-
|
|
|
|
-### `composeReducers(reducer1, reducer2, ...)`
|
|
|
|
-
|
|
|
|
-Creates a wrapper reducer that calls passed reducers
|
|
|
|
-one after another, passing intermediate states.
|
|
|
|
-and returning the result of the last one.
|
|
|
|
-
|
|
|
|
-Useful to "concatenate" a few `subReducer`s. like:
|
|
|
|
-
|
|
|
|
-```js
|
|
|
|
-composeReducers(
|
|
|
|
- subReducer("files.persons", personReducer, "assets.swag"),
|
|
|
|
- subReducer("files.clients", clientReducer, "news"),
|
|
|
|
- subReducer("assets", assetReducer),
|
|
|
|
- baseReducer
|
|
|
|
-)
|
|
|
|
-```
|
|
|
|
-
|
|
|
|
-## Redux helpers
|
|
|
|
|
|
+Access and copy-on-modify JavaScript objects, including maps, using deep paths.
|
|
|
|
|
|
### `deepGetOrNil(key, ...)`
|
|
### `deepGetOrNil(key, ...)`
|
|
### `deget(key, ...)`
|
|
### `deget(key, ...)`
|
|
@@ -344,46 +217,6 @@ using `new Map(obj)`, not using `{...obj}`.
|
|
|
|
|
|
Creates "`obj` as an index in a map".
|
|
Creates "`obj` as an index in a map".
|
|
|
|
|
|
-### `cowValueModel(key, ...)`
|
|
|
|
-
|
|
|
|
-Deprecated.
|
|
|
|
-
|
|
|
|
-Creates an overloaded function allowing
|
|
|
|
-to set or get specified key from any object.
|
|
|
|
-
|
|
|
|
-It gets when one arg passed (works as `deget(key, ...)`),
|
|
|
|
-sets when two args (obj, val) passed (works as `decow(key, ...)(val)(obj)`),
|
|
|
|
-with a caveat: setting `undefined` ends up as plain get
|
|
|
|
-(ES2015 default arguments semantics),
|
|
|
|
-so props are not created when not present
|
|
|
|
-if setting `undefined`; other values including `null` are ok
|
|
|
|
-and create nonpresent props.
|
|
|
|
-
|
|
|
|
-### `typedAction(type, [fn])`
|
|
|
|
-
|
|
|
|
-This creates an action creator function that amends existing `fn` by:
|
|
|
|
- - adding a `type` property to the result, as well as
|
|
|
|
- - adding a `TYPE` property to action creator itself.
|
|
|
|
-
|
|
|
|
-So for example:
|
|
|
|
-
|
|
|
|
-```js
|
|
|
|
-export const answerQuestion =
|
|
|
|
- typedAction("answer question", (index, answer) => ({
|
|
|
|
- payload: {index, answer}
|
|
|
|
- }));
|
|
|
|
-```
|
|
|
|
-
|
|
|
|
-allows you to call `answerQuestion(2, "Albert Einstein")` to create
|
|
|
|
-`{type: "answer question", payload: {index: 2, answer: "Albert Einstein"}}`;
|
|
|
|
-but it also allows you to use `case answerQuestion.TYPE:` in your reducer,
|
|
|
|
-since `answerQuestion.TYPE === "answer question"`.
|
|
|
|
-IOW, this removes the two-space problem of having `const FOO_BAR_TYPE`
|
|
|
|
-as well as `fooBar` action creator.
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-In case you don't pass the `fn` argument, the action creator only creates `{type}`.
|
|
|
|
-
|
|
|
|
### `cowWorkshop(keys, fn = x => x)(obj, [options])`
|
|
### `cowWorkshop(keys, fn = x => x)(obj, [options])`
|
|
|
|
|
|
This is multipurpose enumerate-and-act function to manipulate objects
|
|
This is multipurpose enumerate-and-act function to manipulate objects
|