Let's say I have a reusable container. It is a wizard with multiple pages.
The wizard state is driven by redux/actions. When an action is fired, I use a reducer to update my state.
What if I want to have multiple wizards duplicated, with it's own state?
I am thinking there must be a way to have actions handled by a certain dynamic reducer (that can be created/destroyed), and then have each individual wizard driven from these dynamic pieces of the store/state.
Is this recommended? Are the libraries out there that make this easier?
Just partition your main state into as many wizard states as you need and send a wizard id along with each action so that your reducer knows which one to tackle.
As Array
{ wizards: [ { id: 'A', state: true }, { id: 'B', state: false }, { id: 'C', state: true } ] }
You can write a wizard reducer which understands how to reduce a single wizard state.
function wizardReducer(wizard, action) { switch(action) { case 'TOGGLE': return { id: wizard.id, state: !wizard.state }; default: return wizard; } }
Then write a wizardsReducer
which understands how to reduce a list of wizards.
function wizardsReducer(wizards, action) { return wizards.map(function(wizard) { if(action.id == wizard.id) { return wizardReducer(wizard, action); } else { return wizard; } }); }
Finally, use combineReducers
to create a root reducer which delegates responsibility for the wizards
property to this wizardsReducer
.
combineReducers({ wizards: wizardsReducer });
As Object
If you're storing your wizards in an object instead, you'll have to construct your wizardsReducer
slightly differently.
{ wizards: { A: { id: 'A', state: true }, B: { id: 'B', state: false }, C: { id: 'C', state: true } } }
It wouldn't make much sense to map over the states, when we can just select the state we need straight away.
function wizardsReducer(wizards, action) { if(!(action.id in wizards)) return wizards; const wizard = wizards[action.id]; const updatedWizard = wizardReducer(wizard, action); return { ...wizards, [action.id]: updatedWizard }; }
The OP asked for a lib for this, so I am just throwing it here.
I created infra functions which will intercept the actions and add meta-data
to each action. (following FSA
) You can use this easily to create multiple containers without them affecting each other.
reducer-action-interceptor