更新由另一个减速器管理的状态

IT技术 reactjs redux react-redux
2021-05-10 11:03:35

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

应用程序中的module之一是库存module,它有自己的减速器,即inventoryReducer. 在 redux store 中,我组合了所有的 reducer。

当用户输入库存条目时,除了处理库存事务之外,我还想显示一个在appReducer. 中如何更新的状态displayNotification这是根据appReducerinventoryReducer

以下是我的应用程序减速器:

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_INVENTORYDISPLAY_NOTIFICATION我想知道我怎么可以更新displayNotificationinventoryReducer这里displayNotification实际上是由管理appReducer

2个回答

跟进azium 所说的

我认为你试图做的是错误的方法。是什么阻止你 a)SET_INVENTORY在你的 appReducer 中收听或 b) 从你的组件中分派这两个动作?

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

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

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

选项1

里面 appReducer

你创建一个类型SET_INVENTORY,它做什么DISPLAY_NOTIFICATION对于分派类型SET_INVENTORY(inappReducerinventoryReducer的单个操作,您可以有多个订阅

如下所示,在 中appReducer,如果动作类型为SET_INVENTORYor DISPLAY_NOTIFICATION,reducer 更新 key 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));
    };
}

在 Redux 的官方文档中有一个章节叫做'Beyond combineReducers'它提到了切片缩减器之间的共享数据。

在切片缩减器之间共享数据

我个人更喜欢链接中提到的第三个解决方案,即添加第三个自定义减速器来处理需要跨切片共享数据的“特殊”情况,然后使用reduce-reducers将新的自定义减速器和原始组合减速器结合起来(即appReducer+ inventoryReducer)。

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)