嵌套的redux reducer

时间:2016-04-22 06:15:31

标签: javascript reactjs architecture 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
});

州有结构:

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

auth减速器具有以下结构:

{
    token: 123123123,
    cypher: '256',
    someKey: 123,   
}

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

5 个答案:

答案 0 :(得分:58)

使用keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); keyStore.aliases(); 组合嵌套缩减器完全没问题。但是还有另一种非常方便的模式:嵌套的缩减器。

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 } } 可以将操作转发到authReducerorganisationReducer以更新其状态的某些部分。

答案 1 :(得分:36)

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

例如

// 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
});

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

{
    auth: {
        user: {
            firstName: 'Foo',
            lastName: 'bar',
        }
        organisation: {
            name: 'Foo Bar Co.'
            phone: '1800-123-123',
        },
        security: {
            token: 123123123,
            cypher: '256',
            someKey: 123
        }
    },
    ...
}
如果你无法改变状态结构,那么@ Florent的方法可能会更好

答案 2 :(得分:4)

受到@ florent's答案的启发,我发现你也可以试试这个。不一定比他的回答更好,但我认为它更优雅。

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)}
  }
}

答案 3 :(得分:0)

示例(请参见下面的attachNestedReducers

import { attachNestedReducers } from './utils'
import { profileReducer } from './profile.reducer'
const initialState = { some: 'state' }

const userReducerFn = (state = initialState, action) => {
  switch (action.type) {
    default:
      return state
  }
}

export const userReducer = attachNestedReducers(userReducerFn, {
  profile: profileReducer,
})

状态对象

{
    some: 'state',
    profile: { /* ... */ }
}

这是功能

export function attachNestedReducers(original, reducers) {
  const nestedReducerKeys = Object.keys(reducers)
  return function combination(state, action) {
    const nextState = original(state, action)
    let hasChanged = false
    const nestedState = {}
    for (let i = 0; i < nestedReducerKeys.length; i++) {
      const key = nestedReducerKeys[i]
      const reducer = reducers[key]
      const previousStateForKey = nextState[key]
      const nextStateForKey = reducer(previousStateForKey, action)
      nestedState[key] = nextStateForKey
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey
    }
    return hasChanged ? Object.assign({}, nextState, nestedState) : nextState
  }
}

答案 4 :(得分:0)

嵌套减速器示例:

import {combineReducers} from 'redux';

export default combineReducers({
    [PATH_USER_STATE]: UserReducer,
    [PATH_CART_STATE]: combineReducers({
        [TOGGLE_CART_DROPDOWN_STATE]: CartDropdownVisibilityReducer,
        [CART_ITEMS_STATE]: CartItemsUpdateReducer
    })
});

输出:

{
cart: {toggleCartDropdown: {…}, cartItems: {…}}
user: {currentUser: null}
}