更新由另一个reducer管理的状态

时间:2016-11-30 23:52:16

标签: reactjs redux react-redux

在我的React应用程序中,我的appReducer管理全局内容,例如通知,用户信息等。

应用程序中的一个模块是库存模块,它有自己的reducer,即inventoryReducer。在redux商店中,我将所有减速器组合在一起。

我的问题是:当用户进行库存输入时,除了处理库存交易外,我还想显示在appReducer中处理的屏幕通知。如何从inventoryReducer更新appReducer下的displayNotification状态?

以下是我的app reducer:

import 'babel-polyfill';
import * as types from '../actions/actionTypes';

const initialState = {
    displayNotification: {}
};

export default (state = initialState, action) => {

    switch (action.type) {

        case types.DISPLAY_NOTIFICATION : 
            return Object.assign({}, state, {
                displayNotification: action.value
            })

        default: return state
    }
}

这是inventoryReducer:

import 'babel-polyfill';
import * as types from '../actions/actionTypes';

const initialState = {
    inventory: []
};

export default (state = initialState, action) => {

    switch (action.type) {

        case types.SET_INVENTORY : 
            return Object.assign({}, state, {
                inventory: action.inventoryItem
            })

        case types.DISPLAY_NOTIFICATION : 
            return Object.assign({}, state, {
                app.displayNotification: action.value // <-- Is this how I access displayNotification which is managed by the appReducer?
            })

        default: return state
    }
}

我的更新广告资源操作需要调度SET_INVENTORY和DISPLAY_NOTIFICATION。我正在尝试了解如何从inventoryReducer更新displayNotification,其中displayNotification实际上由appReducer管理。

2 个答案:

答案 0 :(得分:8)

跟着@​​azium所说的,据我所知,在Redux中,每个reducer都被分配了整个状态对象的一个​​片段,并且它们的操作在该片段中受到限制。不允许他们访问由任何其他reducer管理的状态切片,他们不应该这样做。

Redux的概念描述是它是一个可预测的状态容器。但是当我看到我们在这个问题中想要实现的目标时,如果我们要在reducer-A中访问/修改由另一个reducer-B管理的状态,那么应用程序的可预测性和可维护性就会受到影响。

在不妥协任何事情或将不需要的逻辑移入我们的组件的情况下,我们可以实现我们所需要的。

选项1

appReducer

您创建的类型SET_INVENTORY可以执行DISPLAY_NOTIFICATION所做的操作。对于调度类型SET_INVENTORY的单个操作,您可以拥有多个订阅(在appReducer和inventoryReducer中)。

如下所示,在appReducer中,如果操作类型为SET_INVENTORYDISPLAY_NOTIFICATION,则reducer会更新密钥displayNotification

export default (state = initialState, action) => {

    switch (action.type) {

        case types.SET_INVENTORY : 
        case types.DISPLAY_NOTIFICATION : 
            return Object.assign({}, state, {
                displayNotification: action.value
            })

        default: return state
    }
}

选项2

创建一个耦合调度两个动作的方法,

假设你有一个动作

function setInventory(inventoryItem) {
    return {
        type: types.SET_INVENTORY,
        inventoryItem
    };
}

和另一个行动

function displayNotification(value) {
    return {
        type: types.DISPLAY_NOTIFICATION,
        value,
    };
}

创建一个thunk来结合它们:

export function notifyAndSetInventory(notify, inventoryItem) {
    return dispatch => {
        dispatch(displayNotification(notify));
        return dispatch(setInventory(inventoryItem));
    };
}

答案 1 :(得分:2)

在Redux官方文档中有一章叫做“ Beyond CombineReducers”。它提到了在切片缩减器之间共享数据。

https://redux.js.org/recipes/structuring-reducers/beyond-combinereducers#sharing-data-between-slice-reducers

我个人更喜欢链接中提到的第三个解决方案,该解决方案是添加第三个定制化约简器,以处理需要在切片之间共享数据的“特殊”情况,然后使用reduce-reducers组合新的定制化约化器和原始的组合减速器(即appReducer + ventoryReducer)。

const crossSliceReducer = (state, action) => {
  if (action.type === 'CROSS_SLICE_ACTION') {
    // You can access both app and inventory states here
  }
  return state;
}
// Combine the reducers like you did before
const combinedReducer({app: appReducer, inventory: inventoryReducer});

// Add the cross-slice reducer to the root reducer
const rootReducer = reduceReducers(combinedReducer, crossSliceReducer)