Prechádzať zdrojové kódy

subMiddleware, subEffex

Herbert Vojčík 7 rokov pred
rodič
commit
4c5513f892
3 zmenil súbory, kde vykonal 135 pridanie a 49 odobranie
  1. 103 48
      README.md
  2. 24 1
      lib/sac.js
  3. 8 0
      src/sac.js

+ 103 - 48
README.md

@@ -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

+ 24 - 1
lib/sac.js

@@ -3,10 +3,14 @@
 Object.defineProperty(exports, "__esModule", {
     value: true
 });
-exports.composeReducers = exports.subReducer = undefined;
+exports.subEffex = exports.subMiddleware = exports.composeReducers = exports.subReducer = undefined;
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
 
 var _cowValueModel = require("./cow-value-model");
 
+function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
+
 function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
 
 var subReducer = exports.subReducer = function subReducer(key, reducer) {
@@ -40,4 +44,23 @@ var composeReducers = exports.composeReducers = function composeReducers() {
             return r(x, action);
         }, state);
     };
+};
+
+var subMiddleware = function subMiddleware(key, middleware) {
+    var cow = (0, _cowValueModel.cowValueModel)(key);
+    return function (_ref) {
+        var _getState = _ref.getState,
+            rest = _objectWithoutProperties(_ref, ["getState"]);
+
+        return middleware(_extends({ getState: function getState() {
+                return cow(_getState());
+            } }, rest));
+    };
+};
+
+exports.subMiddleware = subMiddleware;
+var subEffex = exports.subEffex = function subEffex(key, effects) {
+    return effects.map(function (each) {
+        return _extends({}, each, { effect: subMiddleware(key, each.effect) });
+    });
 };

+ 8 - 0
src/sac.js

@@ -15,3 +15,11 @@ export const subReducer = (key, reducer, ...otherKeys) => {
 
 export const composeReducers = (...reducers) => (state, action) =>
     reducers.reduce((x, r) => r(x, action), state);
+
+export const subMiddleware = (key, middleware) => {
+    const cow = cowValueModel(key);
+    return ({getState, ...rest}) => middleware({getState: () => cow(getState()), ...rest});
+};
+
+export const subEffex = (key, effects) =>
+    effects.map(each => ({...each, effect: subMiddleware(key, each.effect)}));