For the complete documentation index, see llms.txt. This page is also available as Markdown.

状态管理

本页面介绍如何使用 Redux Toolkit 的 createSlice 和 createEntityAdapter.

何时使用 Slice 与 RTK Query

为你的状态选择合适的工具:

状态类型
工具
示例

远程数据 (由服务器拥有)

RTK Query

用户资料、NFT、目录项、订单

UI 状态 (由客户端拥有)

createSlice

筛选器、模态框、视图偏好、表单状态

规范化集合

createEntityAdapter

已排序/已筛选列表、乐观更新

创建基础 Slice

将 createSlice 用于简单的 UI 状态:

// src/features/ui/ui.slice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import type { RootState } from '@/app/store';

interface UIState {
  sidebarOpen: boolean;
  modalOpen: boolean;
  viewMode: 'grid' | 'list';
  theme: 'light' | 'dark';
}

const initialState: UIState = {
  sidebarOpen: true,
  modalOpen: false,
  viewMode: 'grid',
  theme: 'light',
};

const uiSlice = createSlice({
  name: 'ui',
  initialState,
  reducers: {
    // 布尔切换
    sidebarToggled(state) {
      state.sidebarOpen = !state.sidebarOpen;
    },
    
    // 设置特定值
    modalOpened(state) {
      state.modalOpen = true;
    },
    
    modalClosed(state) {
      state.modalOpen = false;
    },
    
    // Payload 动作
    viewModeChanged(state, action: PayloadAction<'grid' | 'list'>) {
      state.viewMode = action.payload;
    },
    
    themeChanged(state, action: PayloadAction<'light' | 'dark'>) {
      state.theme = action.payload;
    },
    
    // 多个属性
    uiReset() {
      return initialState;
    },
  },
});

// 导出 actions
export const {
  sidebarToggled,
  modalOpened,
  modalClosed,
  viewModeChanged,
  themeChanged,
  uiReset,
} = uiSlice.actions;

// 导出 reducer
export default uiSlice.reducer;

// 导出选择器
export const selectSidebarOpen = (state: RootState) => state.ui.sidebarOpen;
export const selectModalOpen = (state: RootState) => state.ui.modalOpen;
export const selectViewMode = (state: RootState) => state.ui.viewMode;
export const selectTheme = (state: RootState) => state.ui.theme;

使用 Entity Adapter

对于规范化集合(带 ID 的列表),使用 createEntityAdapter:

Entity Adapter 方法

状态修改

生成的选择器

复杂状态示例

在一个 slice 中组合多个关注点:

记忆化选择器

将 createSelector 来自 Reselect,用于计算/派生状态:

使用 extraReducers 的异步逻辑

在你的 slice 中处理 RTK Query 或 async thunk 的响应:

最佳实践

1. 保持状态最小化

2. 使用适合 Immer 的修改方式

3. 合理组织 Reducer

4. 正确为 Action 添加类型

测试 Slice

下一步

最后更新于