【问题标题】:How to manage nested reducers in Redux?如何在 Redux 中管理嵌套的 reducer?
【发布时间】:2020-03-14 03:38:47
【问题描述】:

我有两个仪表板,其中包含我想在 redux 中实现的相似数据和属性。见下文。

Dashboard 1 : {filters, widgets, custom}
Dashboard 2: {filters, widgets, custom}

我想像这样创建我的 redux 状态:

{
dashboards: {
    dashboard1:{
        filter:{ // filter related stuff},
        widgets:{ // widget related state},
        custom:{ // custom state}
    },
    dashboard2: {
        filter:{  // filter related state},
        widgets:{  // widget related state},
        custom:{ // custom state}
    }
},
auth: {// auth related stuff},
...// other state keys

}

为了实现这一点,我正在尝试将这样的组合减速器用于仪表板

// xyz.reducer.js

combineReducers({
filters: filterReducers,
widgets: widgetReducers,
custom: CustomReducers
})

现在我创建了一个仪表板减速器,每次用户导航到某个仪表板时都会调用它。我想根据dashboardID 分配这个状态。像 -

const dashboardReducer = (state = defaultState, action) => {
  switch (action.type) {
    case CREATE_DASHBOARD: {
      const { payload } = action;
      return {
        ...state,
        [payload.dasboardId]: // all the combined reducer state here
      };
    }

    default:
      return state;
  }
};

有人可以建议我如何实现这一目标吗?如果有人有更好的建议,我也愿意提出建议 维护这种状态结构的方式。

【问题讨论】:

  • 如果过滤器和小部件是仪表板的属性,那么为什么它们有自己的减速器?还有什么是CustomReducers?您是否需要同时访问两个仪表板?如果没有,您可以拥有一个减速器,然后根据您应该看到的仪表板将必要的数据传递给一个减速器。或者,您可以拥有一个具有dashboards 属性的仪表板减速器。该键将指向一组仪表板,您可以根据 id 确定要使用的仪表板。
  • 您的仪表板数量是动态的?还是只是用 2 个仪表板固定?
  • @DucHong 现在它是动态的基于用户访问。

标签: reactjs redux react-redux state react-state-management


【解决方案1】:

当然,只要您有办法识别与xyz reducer 相关的所有操作并且可以识别dashboardId,您就可以这样做。

对于您的示例,假设来自 xyz.reducer.js 的嵌套减速器称为 xyz

import xyz from './xyz.reducer.js'; // or whatever

const dashboardReducer = (state = defaultState, action) => {
  switch (action.type) {
    case CREATE_DASHBOARD: {
      const { payload } = action;
      return {
        ...state,
        [payload.dashboardId]: xyz(state[payload.dashboardId], action),
      };
    }

    default:
      return state;
  }
};

假设您知道仪表板可能需要响应您的所有操作类型,并且它们都将dashboardId 作为有效负载中的键,您可以简单地传递所有这些。

const dashboardReducer = (state = defaultState, action) => {
  switch (action.type) {
    case CREATE_DASHBOARD:
    case UPDATE_DASHBOARD_FILTER:
    case ADD_DASHBOARD_WIDGET:
    //... etc
    {
      const { payload } = action;
      return {
        ...state,
        [payload.dashboardId]: xyz(state[payload.dashboardId], action),
      };
    }

    default:
      return state;
  }
};

这有点脆弱,所以你可能想做一些事情,比如假设任何带有仪表板 id 的有效负载都应该被传递:

const dashboardReducer = (state = defaultState, action) => {
  const {payload = {}} = action;
  if (typeof payload.dashboardId !== 'undefined') {
    return {
      ...state,
      [payload.dashboardId]: xyz(state[payload.dashboardId], action),
    };
  }
  return state;
};

现在您无需保留操作类型列表,只需确保所有相关操作创建者在其有效负载中包含 dashboardId

【讨论】:

  • 感谢分享。这看起来是一个非常好的方法。但是当我尝试实现这一点时,我能够触发仪表板内嵌套减速器的操作,即在我的情况下为过滤器/小部件,但没有调用它们相应的减速器。但如果我尝试常规方法,我的减速器工作正常。我已经尝试了与您建议的完全相同的方法,有什么我遗漏的吗?你有任何工作代码示例吗?
  • 这是一个超级快速组合的代码框,它说明了这个概念:codesandbox.io/s/reactredux-vl929 在 reducer 文件中,您将看到 addReducer 用作管理状态的一部分的子 reducer channelReducer 在通过操作有效负载进入的键上动态添加新状态。
猜你喜欢
  • 2018-02-15
  • 1970-01-01
  • 2018-06-03
  • 2020-12-05
  • 1970-01-01
  • 2019-11-16
  • 2017-08-08
  • 1970-01-01
  • 2017-04-03
相关资源
最近更新 更多