Nested redux reducers Nested redux reducers reactjs reactjs

Nested redux reducers


It is perfectly fine to combine your nested reducers using combineReducers. But there is another pattern which is really handy: nested reducers.

const initialState = {  user: null,  organisation: null,  token: null,  cypher: null,  someKey: null,}function authReducer(state = initialState, action) {  switch (action.type) {    case SET_ORGANISATION:      return {...state, organisation: organisationReducer(state.organisation, action)}    case SET_USER:      return {...state, user: userReducer(state.user, action)}    case SET_TOKEN:      return {...state, token: action.token}    default:      return state  }}

In the above example, the authReducer can forward the action to organisationReducer and userReducer to update some part of its state.


Just wanted to elaborate a bit on the very good answer @Florent gave and point out that you can also structure your app a bit differently to achieve nested reducers, by having your root reducer be combined from reducers that are also combined reducers

For example

// src/reducers/index.jsimport { combineReducers } from "redux";import auth from "./auth";import posts from "./posts";import pages from "./pages";import widgets from "./widgets";export default combineReducers({  auth,  posts,  pages,  widgets});// src/reducers/auth/index.js// note src/reducers/auth is instead a directory import { combineReducers } from "redux";import organization from "./organization";import user from "./user";import security from "./security"; export default combineReducers({  user,  organization,  security});

this assumes a bit different of a state structure. Instead, like so:

{    auth: {        user: {            firstName: 'Foo',            lastName: 'bar',        }        organisation: {            name: 'Foo Bar Co.'            phone: '1800-123-123',        },        security: {            token: 123123123,            cypher: '256',            someKey: 123        }    },    ...}

@Florent's approach would likely be better if you're unable to change the state structure, however


Inspired by @florent's answer, I found that you could also try this. Not necessarily better than his answer, but i think it's a bit more elegant.

function userReducer(state={}, action) {    switch (action.type) {    case SET_USERNAME:      state.name = action.name;      return state;    default:      return state;  }} function authReducer(state = {  token: null,  cypher: null,  someKey: null,}, action) {  switch (action.type) {    case SET_TOKEN:      return {...state, token: action.token}    default:      // note: since state doesn't have "user",      // so it will return undefined when you access it.      // this will allow you to use default value from actually reducer.      return {...state, user: userReducer(state.user, action)}  }}