|
@@ -10,13 +10,13 @@ You may use dot notation.
|
|
|
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"]
|
|
|
- // }
|
|
|
+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,
|
|
@@ -32,13 +32,13 @@ 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"]}
|
|
|
- // }
|
|
|
+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.
|
|
@@ -52,12 +52,67 @@ 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
|
|
|
- )
|
|
|
+composeReducers(
|
|
|
+ subReducer("files.persons", personReducer, "assets.swag"),
|
|
|
+ subReducer("files.clients", clientReducer, "news"),
|
|
|
+ subReducer("assets", assetReducer),
|
|
|
+ baseReducer
|
|
|
+)
|
|
|
+```
|
|
|
+
|
|
|
+### `subMiddleware(key, middleware)`
|
|
|
+
|
|
|
+Creates a wrapper middleware
|
|
|
+on the sub-state specified by `key`
|
|
|
+by decorating `getState` part of the passed arg.
|
|
|
+You may use dot notation.
|
|
|
+Rest of the passed arg is left untouched.
|
|
|
+
|
|
|
+```js
|
|
|
+const r = subMiddleware("persons", ({getState}) => next => action => {
|
|
|
+ console.log(JSON.stringify(getState()));
|
|
|
+ return next(action);
|
|
|
+});
|
|
|
+
|
|
|
+// use r 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, effects)`
|
|
|
+
|
|
|
+Creates a wrapper around each element
|
|
|
+of the effects array
|
|
|
+on the sub-state specified by `key`
|
|
|
+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()));
|
|
|
+ }
|
|
|
+}];
|
|
|
+
|
|
|
+// use effects in creation of store
|
|
|
+
|
|
|
+store.getState();
|
|
|
+// => {persons: ["John", "Jill"], cars: ["Honda"]}
|
|
|
+store.dispatch({type: "foo"});
|
|
|
+// console => ["John","Jill"]
|
|
|
```
|
|
|
|
|
|
## Redux helpers
|
|
@@ -74,31 +129,31 @@ Set-usage (two-arg) returns a copy with specified (sub-)property changed;
|
|
|
in case no change actually happens, returns the original object.
|
|
|
|
|
|
```js
|
|
|
- const name = cowValueModel("name");
|
|
|
-
|
|
|
- name({name: "Tom"});
|
|
|
- // => "Tom"
|
|
|
- name({name: "Tom"}, "Jerry");
|
|
|
- // => {name: "Jerry"}
|
|
|
-
|
|
|
- const city = cowValueModel("address.city");
|
|
|
- const city2 = cowValueModel("address", "city");
|
|
|
- const object = {address: {city: "New York"}};
|
|
|
-
|
|
|
- city(object);
|
|
|
- // => "New York"
|
|
|
- city2(object);
|
|
|
- // => "New York"
|
|
|
- city(object, "London");
|
|
|
- // => {address: {city: "London"}}
|
|
|
- city2(object, "London");
|
|
|
- // => {address: {city: "London"}}
|
|
|
- object;
|
|
|
- // => {address: {city: "New York"}}
|
|
|
- city(object, "New York") === object;
|
|
|
- // => true
|
|
|
- city2(object, "New York") === object;
|
|
|
- // => true
|
|
|
+const name = cowValueModel("name");
|
|
|
+
|
|
|
+name({name: "Tom"});
|
|
|
+// => "Tom"
|
|
|
+name({name: "Tom"}, "Jerry");
|
|
|
+// => {name: "Jerry"}
|
|
|
+
|
|
|
+const city = cowValueModel("address.city");
|
|
|
+const city2 = cowValueModel("address", "city");
|
|
|
+const object = {address: {city: "New York"}};
|
|
|
+
|
|
|
+city(object);
|
|
|
+// => "New York"
|
|
|
+city2(object);
|
|
|
+// => "New York"
|
|
|
+city(object, "London");
|
|
|
+// => {address: {city: "London"}}
|
|
|
+city2(object, "London");
|
|
|
+// => {address: {city: "London"}}
|
|
|
+object;
|
|
|
+// => {address: {city: "New York"}}
|
|
|
+city(object, "New York") === object;
|
|
|
+// => true
|
|
|
+city2(object, "New York") === object;
|
|
|
+// => true
|
|
|
```
|
|
|
|
|
|
If you put a number in a list of keys to use,
|
|
@@ -119,9 +174,9 @@ So for example:
|
|
|
|
|
|
```js
|
|
|
export const answerQuestion =
|
|
|
- typedAction("answer question", (index, answer) => ({
|
|
|
- payload: {index, answer}
|
|
|
- }));
|
|
|
+ typedAction("answer question", (index, answer) => ({
|
|
|
+ payload: {index, answer}
|
|
|
+ }));
|
|
|
```
|
|
|
|
|
|
allows you to call `answerQuestion(2, "Albert Einstein")` to create
|