You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Redux combineReducers实现含自有属性的嵌套reducer结构

如何在Redux中让addPage节点同时包含子reducer和自身属性

要实现你想要的状态结构,核心思路是不能直接用combineReducers生成addPage节点——因为combineReducers只能让每个子reducer对应独立的状态节点,无法处理父节点自身的属性。你需要手动编写一个顶层的addPageReducer,它既要处理自身的shopListDisplayedrerenderKey属性,又要调用combineReducers来管理productshop这两个子节点。

下面是具体的实现步骤和代码示例:

1. 先定义子reducer(product和shop)

先写好负责productshop状态的独立reducer,和平时的写法一样:

// productReducer.js
const initialProductState = { /* 你的product初始状态 */ };
export const productReducer = (state = initialProductState, action) => {
  switch(action.type) {
    case 'ADD_PRODUCT':
      return {...state, ...action.payload};
    // 其他product相关action处理
    default:
      return state;
  }
};

// shopReducer.js
const initialShopState = { /* 你的shop初始状态 */ };
export const shopReducer = (state = initialShopState, action) => {
  switch(action.type) {
    case 'UPDATE_SHOP_INFO':
      return {...state, ...action.payload};
    // 其他shop相关action处理
    default:
      return state;
  }
};

2. 定义addPage的初始状态

这个状态要同时包含自身属性和子reducer的初始值:

const initialAddPageState = {
  shopListDisplayed: false,
  rerenderKey: 0,
  product: initialProductState, // 对应productReducer的初始状态
  shop: initialShopState       // 对应shopReducer的初始状态
};

3. 编写addPage的顶层reducer

这个reducer是核心:它先处理自身属性的action,再把非自身的action转发给子reducer处理:

import { combineReducers } from 'redux';
import { productReducer, shopReducer } from './path-to-reducers';

// 先用combineReducers把product和shop的reducer合并成一个子处理函数
const addPageChildReducers = combineReducers({
  product: productReducer,
  shop: shopReducer
});

// 编写addPage的顶层reducer
export const addPageReducer = (state = initialAddPageState, action) => {
  // 优先处理addPage自身属性的action
  switch(action.type) {
    case 'TOGGLE_SHOP_LIST_DISPLAY':
      return {
        ...state,
        shopListDisplayed: !state.shopListDisplayed
      };
    case 'INCREMENT_RENDER_KEY':
      return {
        ...state,
        rerenderKey: state.rerenderKey + 1
      };
    // 其他自身属性的action都在这里处理
    default:
      // 非自身的action,交给子reducer处理product和shop的状态更新
      const updatedChildState = addPageChildReducers(state, action);
      return {
        ...state,
        ...updatedChildState
      };
  }
};

4. 将addPageReducer加入根reducer

最后把addPageReducer放到根combineReducers中,作为addPage节点的处理函数:

import { combineReducers } from 'redux';
import { addPageReducer } from './path-to-addPageReducer';

const rootReducer = combineReducers({
  addPage: addPageReducer,
  // 其他根节点的reducer...
});

export default rootReducer;

最终的状态结构

这样配置后,你的Redux状态就会变成你想要的样子:

{
  addPage: {
    shopListDisplayed: false,
    rerenderKey: 0,
    product: { /* productReducer管理的状态 */ },
    shop: { /* shopReducer管理的状态 */ }
  }
}

补充说明

如果你的子reducer数量很少,也可以不用combineReducers,手动转发action给子reducer,比如:

export const addPageReducer = (state = initialAddPageState, action) => {
  switch(action.type) {
    // 处理自身属性的action...
    default:
      return {
        ...state,
        product: productReducer(state.product, action),
        shop: shopReducer(state.shop, action)
      };
  }
};

这种写法更直观,但子reducer多的时候会比较繁琐,推荐用combineReducers来简化代码。

内容的提问来源于stack exchange,提问作者BeniaminoBaggins

火山引擎 最新活动