Reducing an entire subtree with combix combix

I have a reducer tree that looks like this:

module.exports = combineReducers({ routing: routeReducer, app: combineReducers({ setup: combineReducers({ sets, boosters }), servers: combineReducers({ servers }) }) }); 

Now the setup key stores the form, which should be reset after it is submitted. However, I do not have access to the entire setup tree, because using combReducers means that reducers only manipulate data in the leaf nodes of the tree ( sets and boosters ).

My first impulse is to create a function that reduces the entire installation tree as follows:

 function setup(state, action){ //If there an action that affects this whole tree, handle it switch(action.type){ case "FORM_SUBMIT": //DO STUFF break; } //Otherwise just let the reducers care about their own data return combineReducers({ sets, boosters })(state); } 

But this will not work, and also ruin the beautiful tree structure of my first code sample.

Is there a better solution for this with redux?

+5
source share
2 answers

combineReducers is a good template because it tends to provide the idea that gears should be tied to non-overlapping subsets of the store, separated from the structure of the store itself. Express the view that you should reduce leaves, not branches, and handle branch reduction.

However, there may be good reasons to use an alternative template. As I mentioned in the question higher order function . It may be hard to understand, but here's how I approach it:

  • We know that setupReducer takes a reducer as an argument because we pass the result of combineReducers .
  • We know that the reducer signature returned by combineReducers is (state, action) => state .
  • We also know that setupReducer must return a reducer, which, again, is a signature function (state, action) => state .

In other words, it takes the gearbox and returns the gearbox: ((state, action) => state) => ((state, action) => state) . So it might look like this:

 function setupReducer(subReducer) { return (state, action) => { //If there an action that affects this whole tree, handle it switch(action.type){ case "FORM_SUBMIT": // ... create newState return newState; default: return subReducer(state, action); } } } 

I saved your logical stream above, but, as a warning, you can unconditionally call subReducer and then change its output. Otherwise, you will need to make sure that your branches, where it is not called, always create an object of the same shape that seems to be a potential sticky adhesion point.

+7
source

@acjay's answer is a great idea! I just wanted to use the old reducer(state, action) method, and not a higher order function. So I created a method that makes up the reducer in the master-follower relationship.

Master slave

 export default function masterSlaveReducer(reducerMaster, reducerSlave) { return (state, action) => { const newState = reducerMaster(state, action); if(newState === state){ return reducerSlave(state, action); } return newState; }; } 

Then the Miguel code will be used as follows:

 module.exports = combineReducers({ routing: routeReducer, app: combineReducers({ setup: masterSlaveReducer( setup, // setup() from Miguel question combineReducers({ sets, boosters }) ), servers: combineReducers({ servers }) }) }); 
0
source

Source: https://habr.com/ru/post/1239001/


All Articles