You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redux:是否存在更优的reducer编写方式?

Addressing Common Redux Reducer Pain Points

Great question—you’ve hit on some of the most common pain points people run into when writing Redux reducers, especially as apps scale up. Let’s break down each of your concerns and talk about practical fixes:

1. Reducer Bloat & Violating the Single Responsibility Principle

reducer过于通用(你完全可以编写臃肿的reducer来处理各类不同的action,极易造成混乱),至少这违背了单一职责原则(Single Responsibility Principle)

The core fix here is splitting your reducers into smaller, focused slices that each handle only a specific piece of your state. Instead of one giant reducer managing user auth, cart state, and UI preferences all at once, create separate reducers like authReducer, cartReducer, and uiReducer.

You can combine these using Redux's built-in combineReducers() utility, which lets each slice handle its own actions without interfering with others. This keeps each reducer focused on one job, aligning perfectly with the Single Responsibility Principle and making your codebase way easier to navigate.

2. Maintenance Headaches with Switch Statements

switch语句会带来维护副作用,例如修改某个case可能会破坏其他已正常运行的case

Switch statements aren’t inherently evil, but they do become unwieldy as you add more action types. A cleaner alternative is to use a reducer lookup object: map action type strings directly to handler functions, instead of relying on switch cases.

Here’s a concrete example:

const initialCartState = { items: [], total: 0 };

const cartReducer = (state = initialCartState, action) => {
  const actionHandlers = {
    ADD_ITEM: (state, action) => ({
      ...state,
      items: [...state.items, action.payload],
      total: state.total + action.payload.price
    }),
    REMOVE_ITEM: (state, action) => {
      const updatedItems = state.items.filter(item => item.id !== action.payload);
      return {
        ...state,
        items: updatedItems,
        total: updatedItems.reduce((sum, item) => sum + item.price, 0)
      };
    },
    UPDATE_QUANTITY: (state, action) => ({
      ...state,
      items: state.items.map(item => 
        item.id === action.payload.id 
          ? { ...item, quantity: action.payload.quantity } 
          : item
      )
    })
  };

  // Return the result of the handler if it exists, else return current state
  return actionHandlers[action.type] ? actionHandlers[action.type](state, action) : state;
};

This pattern makes it way easier to scan, update, or remove handlers without risking accidental changes to unrelated logic. Plus, you can extract complex handlers into separate functions if needed, keeping your reducer clean.

3. Repeating default: return state (Violating DRY)

始终重复出现的‘default: return state’(违反DRY原则)

The lookup object pattern above already eliminates this repetition by defaulting to returning the current state when no matching handler exists. But if you still prefer switch statements, you can create a reusable utility function that wraps your reducer logic and handles the default case automatically.

Here’s how that works:

// Reusable reducer creator
const createReducer = (initialState, actionHandlers) => {
  return (state = initialState, action) => {
    if (actionHandlers.hasOwnProperty(action.type)) {
      return actionHandlers[action.type](state, action);
    }
    // Default case is handled once here
    return state;
  };
};

// Usage for an auth reducer
const initialAuthState = { user: null, isAuthenticated: false };
const authReducer = createReducer(initialAuthState, {
  LOGIN_SUCCESS: (state, action) => ({
    ...state,
    user: action.payload,
    isAuthenticated: true
  }),
  LOGOUT: (state) => ({
    ...state,
    user: null,
    isAuthenticated: false
  })
});

Now you never have to write that default: return state line again—your utility takes care of it for every reducer you create, keeping your code DRY and consistent.


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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 06:57:37