嵌套的redux reducer

And*_*gan 54 javascript architecture reactjs react-native redux

是否可以组合使用以下结构嵌套的Reducer:

import 'user' from ...
import 'organisation' from ...
import 'auth' from ...
// ...

export default combineReducers({
  auth: {
    combineReducers({
        user,
        organisation,  
    }),
    auth,
  },
  posts,
  pages,
  widgets,
  // .. more state here
});
Run Code Online (Sandbox Code Playgroud)

国家的结构如何:

{
    auth: {
        user: {
            firstName: 'Foo',
            lastName: 'bar',
        }
        organisation: {
            name: 'Foo Bar Co.'
            phone: '1800-123-123',
        },
        token: 123123123,
        cypher: '256',
        someKey: 123,
    }
}
Run Code Online (Sandbox Code Playgroud)

auth减速机具有结构:

{
    token: 123123123,
    cypher: '256',
    someKey: 123,   
}
Run Code Online (Sandbox Code Playgroud)

也许扩散算子很方便?...auth不确定 :-(

Flo*_*ent 66

使用嵌套Reducer进行组合是完全正常的combineReducers.但是还有另一种非常方便的模式:嵌套的缩减器.

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
  }
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,authReducer可以将操作转发到organisationReduceruserReducer更新其状态的某些部分.

  • @Florent如果organisationReducer有很多动作怎么办?我需要在外部和内部缩减器中复制"case"吗?根据您的示例,organisationReducer处理的唯一操作是SET_ORGANISATION (6认同)
  • 很高兴看到 `organisationReducer` 和 `authReducer` 的代码。 (4认同)

Jos*_*lds 42

只是想详细说明@Florent给出的非常好的答案,并指出你也可以通过将减速器与减速器组合使用来减少器,从而有点不同地构建你的应用程序以实现嵌套减速器

例如

// src/reducers/index.js
import { 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
});
Run Code Online (Sandbox Code Playgroud)

这假设状态结构略有不同.相反,像这样:

{
    auth: {
        user: {
            firstName: 'Foo',
            lastName: 'bar',
        }
        organisation: {
            name: 'Foo Bar Co.'
            phone: '1800-123-123',
        },
        security: {
            token: 123123123,
            cypher: '256',
            someKey: 123
        }
    },
    ...
}
Run Code Online (Sandbox Code Playgroud)

但是,如果你无法改变国家结构,@ Florent的方法可能会更好

  • 随着州的发展,这种解决方案似乎更容易维护. (5认同)

D.W*_*D.W 6

受到@ florent的回答的启发,我发现您也可以尝试一下。不一定比他的答案更好,但我认为它稍微优雅一些​​。

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)}
  }
}
Run Code Online (Sandbox Code Playgroud)