Skip to content

状态管理方案选型 - 全面对比主流方案

1. 状态管理方案概览

1.1 主流方案

typescript
const stateManagementSolutions = {
  内置方案: {
    useState: '组件本地状态',
    useReducer: '复杂本地状态',
    Context: '跨组件共享',
    特点: '无需额外依赖'
  },
  
  Redux生态: {
    Redux: '经典方案',
    ReduxToolkit: 'Redux官方推荐',
    特点: '可预测、中间件丰富'
  },
  
  原子化方案: {
    Recoil: 'Facebook出品',
    Jotai: '轻量级原子状态',
    特点: '细粒度订阅'
  },
  
  响应式方案: {
    MobX: '响应式状态',
    Valtio: '代理状态',
    特点: '自动追踪依赖'
  },
  
  轻量方案: {
    Zustand: '极简状态管理',
    Valtio: '代理状态',
    特点: 'API简单、包体积小'
  }
};

1.2 选型矩阵

typescript
const selectionMatrix = {
  应用规模: {
    小型: 'useState + Context',
    中型: 'Zustand / Jotai',
    大型: 'Redux Toolkit / MobX'
  },
  
  状态复杂度: {
    简单: 'useState',
    中等: 'useReducer / Zustand',
    复杂: 'Redux / MobX'
  },
  
  团队经验: {
    新手: 'useState + Context',
    中级: 'Zustand / Jotai',
    高级: 'Redux / MobX'
  },
  
  性能要求: {
    一般: 'Context',
    较高: 'Zustand / Jotai',
    很高: 'Redux + Reselect'
  }
};

2. 方案详细对比

2.1 Redux Toolkit

typescript
const reduxToolkit = {
  优势: [
    '官方推荐',
    '简化Redux使用',
    '内置Immer',
    '优秀的DevTools',
    '强大的中间件'
  ],
  
  示例: `
    import { createSlice, configureStore } from '@reduxjs/toolkit';
    
    const counterSlice = createSlice({
      name: 'counter',
      initialState: { value: 0 },
      reducers: {
        increment: state => { state.value += 1; },
        decrement: state => { state.value -= 1; }
      }
    });
    
    const store = configureStore({
      reducer: { counter: counterSlice.reducer }
    });
    
    // 使用
    const count = useSelector(state => state.counter.value);
    const dispatch = useDispatch();
    dispatch(counterSlice.actions.increment());
  `,
  
  适用场景: [
    '大型应用',
    '复杂状态逻辑',
    '需要时间旅行调试',
    '团队协作'
  ]
};

2.2 Zustand

typescript
const zustand = {
  优势: [
    'API极简',
    '包体积小(1KB)',
    '无需Provider',
    'TypeScript友好',
    '性能优秀'
  ],
  
  示例: `
    import create from 'zustand';
    
    const useStore = create((set) => ({
      count: 0,
      increment: () => set(state => ({ count: state.count + 1 })),
      decrement: () => set(state => ({ count: state.count - 1 }))
    }));
    
    // 使用
    function Counter() {
      const count = useStore(state => state.count);
      const increment = useStore(state => state.increment);
      
      return <button onClick={increment}>{count}</button>;
    }
  `,
  
  适用场景: [
    '中小型应用',
    '快速开发',
    '简单状态逻辑',
    '不需要复杂调试'
  ]
};

2.3 Jotai

typescript
const jotai = {
  优势: [
    '原子化状态',
    '细粒度更新',
    '最小重渲染',
    'TypeScript优秀',
    '支持异步'
  ],
  
  示例: `
    import { atom, useAtom } from 'jotai';
    
    const countAtom = atom(0);
    const doubleAtom = atom(get => get(countAtom) * 2);
    
    function Counter() {
      const [count, setCount] = useAtom(countAtom);
      const [double] = useAtom(doubleAtom);
      
      return (
        <div>
          <p>Count: {count}</p>
          <p>Double: {double}</p>
          <button onClick={() => setCount(c => c + 1)}>+</button>
        </div>
      );
    }
  `,
  
  适用场景: [
    '需要细粒度更新',
    '派生状态较多',
    '中小型应用',
    '性能敏感'
  ]
};

2.4 MobX

typescript
const mobx = {
  优势: [
    '响应式编程',
    '自动追踪依赖',
    '简单的API',
    '优秀的性能'
  ],
  
  示例: `
    import { makeAutoObservable } from 'mobx';
    import { observer } from 'mobx-react-lite';
    
    class CounterStore {
      count = 0;
      
      constructor() {
        makeAutoObservable(this);
      }
      
      increment() {
        this.count++;
      }
      
      get double() {
        return this.count * 2;
      }
    }
    
    const counterStore = new CounterStore();
    
    const Counter = observer(() => {
      return (
        <div>
          <p>{counterStore.count}</p>
          <p>{counterStore.double}</p>
          <button onClick={() => counterStore.increment()}>+</button>
        </div>
      );
    });
  `,
  
  适用场景: [
    '熟悉OOP',
    '复杂派生状态',
    '大型应用',
    '需要自动追踪'
  ]
};

4. 实战选型

4.1 项目类型选择

typescript
const projectTypeSelection = {
  个人项目: 'useState + Context或Zustand',
  
  中小型商业: 'Zustand或Jotai',
  
  大型企业: 'Redux Toolkit',
  
  高性能需求: 'Jotai或MobX',
  
  快速原型: 'Zustand',
  
  团队协作: 'Redux Toolkit (标准化)',
  
  示例决策树: `
    是否需要时间旅行调试?
      是 -> Redux Toolkit
      否 -> 继续
    
    是否是大型应用?
      是 -> Redux Toolkit / MobX
      否 -> 继续
    
    团队是否熟悉Redux?
      是 -> Redux Toolkit
      否 -> 继续
    
    是否需要细粒度更新?
      是 -> Jotai / MobX
      否 -> Zustand
  `
};

5. 面试高频问题

typescript
const interviewQA = {
  Q1: {
    question: '如何选择状态管理方案?',
    answer: [
      '1. 考虑应用规模',
      '2. 评估状态复杂度',
      '3. 考虑团队经验',
      '4. 性能要求',
      '5. 调试需求',
      '6. 生态系统'
    ]
  },
  
  Q2: {
    question: '各方案的性能对比?',
    answer: `
      精确订阅: Redux > Jotai > Zustand > Context
      包大小: Zustand < Jotai < Redux Toolkit
      学习曲线: useState < Zustand < Jotai < Redux
    `
  }
};

6. 总结

状态管理方案选型的核心要点:

  1. 内置方案: 适合简单场景
  2. Redux: 大型应用首选
  3. Zustand: 中小型应用最佳
  4. Jotai: 细粒度更新优秀
  5. MobX: 响应式编程
  6. 选型: 根据项目特点选择

没有最好的方案,只有最合适的方案。

7. Valtio深入解析

7.1 Valtio核心概念

javascript
import { proxy, useSnapshot } from 'valtio';

const state = proxy({
  count: 0,
  user: { name: 'John', age: 30 },
  todos: []
});

function increment() {
  state.count++;
}

function Counter() {
  const snap = useSnapshot(state);
  return <button onClick={increment}>{snap.count}</button>;
}

7.2 Valtio优劣势

typescript
const valtioComparison = {
  优势: ['极简API', '自动追踪', '直接修改', 'TypeScript友好', '体积小1KB'],
  劣势: ['Proxy兼容性', '调试工具少', '生态较小'],
  适用: ['中小型应用', '简单状态管理', 'Vue风格团队']
};

8. Recoil深入解析

8.1 Recoil核心概念

javascript
import { atom, selector, useRecoilState, useRecoilValue } from 'recoil';

const textState = atom({
  key: 'textState',
  default: ''
});

const charCountState = selector({
  key: 'charCountState',
  get: ({ get }) => {
    const text = get(textState);
    return text.length;
  }
});

const userInfoQuery = selector({
  key: 'userInfoQuery',
  get: async ({ get }) => {
    const userId = get(currentUserIdState);
    const response = await fetch(`/api/users/${userId}`);
    return response.json();
  }
});

const todoItemState = atomFamily({
  key: 'todoItemState',
  default: (id) => ({ id, text: '', completed: false })
});

8.2 Recoil优劣势

typescript
const recoilComparison = {
  优势: ['细粒度更新', '原生异步支持', 'Concurrent Mode集成', 'Atom清晰', '代码分割'],
  劣势: ['实验性项目', 'API可能变化', '学习曲线陡', '调试工具有限'],
  适用: ['细粒度状态', '大量派生状态', '异步管理', 'Concurrent项目']
};

9. XState深入解析

9.1 XState核心概念

javascript
import { createMachine, interpret, assign } from 'xstate';
import { useMachine } from '@xstate/react';

const authMachine = createMachine({
  id: 'auth',
  initial: 'idle',
  context: { user: null, error: null },
  states: {
    idle: { on: { LOGIN: 'loading' } },
    loading: {
      invoke: {
        id: 'loginService',
        src: (context, event) => loginUser(event.credentials),
        onDone: { target: 'authenticated', actions: assign({ user: (_, event) => event.data }) },
        onError: { target: 'error', actions: assign({ error: (_, event) => event.data }) }
      }
    },
    authenticated: { on: { LOGOUT: 'idle' } },
    error: { on: { RETRY: 'loading' } }
  }
});

function AuthComponent() {
  const [state, send] = useMachine(authMachine);
  
  if (state.matches('idle')) return <button onClick={() => send({ type: 'LOGIN', credentials: {} })}>Login</button>;
  if (state.matches('loading')) return <Loading />;
  if (state.matches('authenticated')) return <div>Welcome, {state.context.user.name}! <button onClick={() => send('LOGOUT')}>Logout</button></div>;
  if (state.matches('error')) return <div>Error: {state.context.error.message} <button onClick={() => send('RETRY')}>Retry</button></div>;
}

9.2 XState优劣势

typescript
const xstateComparison = {
  优势: ['状态可视化', '避免非法状态', '复杂逻辑清晰', '测试友好', '状态图生成'],
  劣势: ['学习曲线陡', '样板代码多', '简单场景过度设计', '包体积大'],
  适用: ['复杂状态转换', '工作流管理', '多步骤表单', '需要可视化']
};

10. 选型决策树

10.1 选型流程

typescript
const decisionTree = {
  项目规模: {
    小型: { 推荐: ['useState', 'Context'], 原因: '简单直接' },
    中型: { 推荐: ['Zustand', 'Jotai', 'Valtio'], 原因: '轻量完整' },
    大型: { 推荐: ['Redux Toolkit', 'MobX'], 原因: '生态成熟' }
  },
  团队背景: {
    熟悉Redux: { 推荐: 'Redux Toolkit', 原因: '降低学习成本' },
    熟悉Vue: { 推荐: ['Valtio', 'MobX'], 原因: '响应式相似' },
    新手: { 推荐: ['Zustand', 'Context'], 原因: 'API简单' }
  },
  性能要求: {
    高频更新: { 推荐: ['Jotai', 'Recoil', 'Zustand'], 原因: '细粒度更新' },
    一般: { 推荐: ['Redux Toolkit', 'Context'], 原因: '平衡性能开发' }
  },
  特殊需求: {
    时间旅行: { 推荐: 'Redux Toolkit', 原因: 'DevTools' },
    状态机: { 推荐: 'XState', 原因: '专为状态机设计' },
    服务端状态: { 推荐: ['React Query', 'SWR', 'RTK Query'], 原因: '数据获取优化' }
  }
};

10.2 实际案例

typescript
const realCases = [
  { 项目: '电商平台', 规模: '大型', 选择: 'Redux Toolkit + RTK Query', 原因: ['复杂状态', '调试工具', '团队熟悉', 'API请求'] },
  { 项目: 'Todo应用', 规模: '小型', 选择: 'Context + useReducer', 原因: ['状态简单', '无需依赖', '学习成本低'] },
  { 项目: '数据看板', 规模: '中型', 选择: 'Zustand + React Query', 原因: ['UI状态', '服务端数据', '高频更新', 'API简单'] },
  { 项目: '协作编辑', 规模: '大型', 选择: 'Yjs + Zustand', 原因: ['协作同步', 'UI状态', '实时需求'] },
  { 项目: '表单流程', 规模: '中型', 选择: 'XState + React Hook Form', 原因: ['复杂流程', '多步骤', '状态清晰', '表单验证'] }
];

11. 混合使用策略

11.1 分层状态管理

jsx
import { useQuery, useMutation } from '@tanstack/react-query';
import create from 'zustand';

function UserList() {
  const { data: users } = useQuery({ queryKey: ['users'], queryFn: fetchUsers });
  return <div>{/* 展示用户 */}</div>;
}

const useUIStore = create((set) => ({
  sidebarOpen: false,
  theme: 'light',
  toggleSidebar: () => set(state => ({ sidebarOpen: !state.sidebarOpen })),
  setTheme: (theme) => set({ theme })
}));

function App() {
  const { sidebarOpen, toggleSidebar } = useUIStore();
  return <div><button onClick={toggleSidebar}>Toggle</button>{sidebarOpen && <Sidebar />}</div>;
}

const cartSlice = createSlice({
  name: 'cart',
  initialState: { items: [] },
  reducers: { addItem: (state, action) => { state.items.push(action.payload); } }
});

import { useForm } from 'react-hook-form';

function LoginForm() {
  const { register, handleSubmit } = useForm();
  const onSubmit = (data) => {};
  return <form onSubmit={handleSubmit(onSubmit)}><input {...register('email')} /><button>Login</button></form>;
}

11.2 混合策略

typescript
const hybridStrategy = {
  服务端状态: { 工具: ['React Query', 'SWR', 'RTK Query'], 负责: ['数据获取', '缓存', '重试', '轮询'] },
  UI状态: { 工具: ['Zustand', 'Jotai', 'Context'], 负责: ['主题', '侧边栏', '模态框', '输入'] },
  全局业务: { 工具: ['Redux Toolkit', 'MobX'], 负责: ['用户', '购物车', '通知'] },
  表单: { 工具: ['React Hook Form', 'Formik'], 负责: ['验证', '字段管理'] },
  路由: { 工具: ['React Router', 'Next.js'], 负责: ['导航', '参数'] }
};

12. 性能对比

12.1 渲染次数

typescript
const performanceTest = {
  Context: { renders: 100, time: '~500ms', reason: '全量通知' },
  Redux: { renders: 10, time: '~100ms', reason: '精确订阅' },
  Zustand: { renders: 10, time: '~90ms', reason: '精确订阅' },
  Jotai: { renders: 10, time: '~85ms', reason: '原子化更新' },
  MobX: { renders: 10, time: '~95ms', reason: '自动追踪' }
};

12.2 Bundle大小

typescript
const bundleSize = {
  React内置: { useState: '0KB', useReducer: '0KB', Context: '0KB' },
  轻量: { Zustand: '~1.1KB', Jotai: '~2.9KB', Valtio: '~1.2KB' },
  中量: { 'React Query': '~13KB', XState: '~17KB' },
  重量: { 'Redux Toolkit': '~48KB', MobX: '~19KB', Recoil: '~21KB' }
};

13. 迁移指南

13.1 Redux到Zustand

javascript
// Redux
const initialState = { count: 0 };
function counterReducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT': return { ...state, count: state.count + 1 };
    default: return state;
  }
}
const store = createStore(counterReducer);

function Counter() {
  const count = useSelector(state => state.count);
  const dispatch = useDispatch();
  return <button onClick={() => dispatch({ type: 'INCREMENT' })}>{count}</button>;
}

// Zustand
const useCounterStore = create((set) => ({
  count: 0,
  increment: () => set(state => ({ count: state.count + 1 }))
}));

function Counter() {
  const { count, increment } = useCounterStore();
  return <button onClick={increment}>{count}</button>;
}

13.2 Context到Jotai

jsx
// Context
const CountContext = createContext();
function CountProvider({ children }) {
  const [count, setCount] = useState(0);
  return <CountContext.Provider value={{ count, setCount }}>{children}</CountContext.Provider>;
}
function Counter() {
  const { count, setCount } = useContext(CountContext);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

// Jotai
import { atom, useAtom } from 'jotai';
const countAtom = atom(0);
function Counter() {
  const [count, setCount] = useAtom(countAtom);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

14. 面试重点

14.1 高频面试题

typescript
const questions = [
  { q: '如何选择状态管理方案?', a: '考虑:项目规模、团队背景、性能要求、特殊需求、学习成本' },
  { q: '5种方案特点?', a: 'Context简单内置、Redux功能强大、Zustand轻量简洁、Jotai原子化、MobX响应式' },
  { q: 'Zustand vs Redux场景?', a: 'Zustand适合中小型、不需复杂中间件、追求简洁API、团队经验少、不需时间旅行' },
  { q: '如何混合使用?', a: '分层:React Query服务端、Zustand全局业务、Context配置、Hook Form表单、useState局部UI' },
  { q: 'Jotai vs Recoil区别?', a: '相同:原子化、派生状态。不同:Jotai更轻量2.9KB vs 21KB、API更简单、Recoil实验性' }
];

14.2 最佳实践

typescript
const practices = {
  通用: ['优先React内置', '服务端状态用专门库', '避免过度设计', '考虑团队栈', '性能非首要'],
  小型: ['Context + useReducer', '或Zustand', '避免Redux'],
  中型: ['Zustand + React Query', '或Jotai + React Query'],
  大型: ['Redux Toolkit + RTK Query', '或MobX + React Query', '需要调试工具'],
  特殊: ['状态机用XState', '协作用Yjs', '表单用Hook Form']
};

15. 状态管理演进

15.1 历史演进

typescript
const evolution = {
  '2013-2015': { 方案: 'Flux', 特点: '单向数据流概念' },
  '2015-2018': { 方案: 'Redux', 特点: '统一标准,生态繁荣' },
  '2018-2020': { 方案: 'Context + Hooks', 特点: 'React内置方案成熟' },
  '2020-2022': { 方案: 'Zustand/Jotai/Recoil', 特点: '轻量化、原子化' },
  '2022-现在': { 方案: 'React Query/SWR', 特点: '服务端状态专门化' },
  '未来': { 方案: 'React Forget', 特点: '自动优化,减少状态管理' }
};

15.2 趋势分析

typescript
const trends = {
  轻量化: '从Redux 48KB到Zustand 1KB',
  原子化: 'Jotai/Recoil细粒度状态',
  专门化: 'React Query处理服务端,Zustand处理UI',
  自动化: 'React Compiler自动优化,减少手动管理',
  类型化: 'TypeScript集成越来越好'
};

16. 企业级实践

16.1 大型项目架构

typescript
const enterpriseArchitecture = {
  层次: {
    '1. 服务端状态层': 'RTK Query统一API管理',
    '2. 全局业务层': 'Redux Toolkit核心业务逻辑',
    '3. UI状态层': 'Zustand管理UI交互',
    '4. 表单层': 'React Hook Form验证',
    '5. 路由层': 'React Router导航'
  },
  规范: ['统一Store结构', 'Action命名规范', 'Selector模式', '错误处理', '日志系统'],
  工具: ['Redux DevTools', 'React Query DevTools', 'Sentry监控', 'CI/CD集成']
};

16.2 团队协作

typescript
const teamwork = {
  代码规范: ['统一状态管理方案', 'Slice命名规范', 'Action类型规范', 'Selector复用'],
  文档: ['状态流程图', 'API文档', '迁移指南', '最佳实践'],
  培训: ['新人培训', '代码审查', '知识分享', '案例分析'],
  工具: ['类型定义', 'ESLint规则', 'Git Hooks', 'CI检查']
};

17. Pinia状态管理

17.1 Pinia概述

typescript
// Pinia是Vue 3官方状态管理库,但其思想可借鉴到React

const piniaFeatures = {
  特点: [
    '轻量级',
    'TypeScript支持优秀',
    '模块化设计',
    '组合式API',
    '插件系统'
  ],
  
  对React的启示: [
    '简洁的API设计',
    '模块化状态管理',
    'TypeScript优先',
    '扁平化Store结构'
  ]
};

// React中类似Pinia的实现
import create from 'zustand';

const useUserStore = create((set, get) => ({
  user: null,
  token: null,
  
  // Actions
  setUser: (user) => set({ user }),
  setToken: (token) => set({ token }),
  
  // Getters
  get isAuthenticated() {
    return !!get().token;
  },
  
  get userName() {
    return get().user?.name || 'Guest';
  }
}));

17.2 Pinia风格在React中的应用

typescript
// 借鉴Pinia的设计理念创建React Store

interface UserState {
  user: User | null;
  loading: boolean;
  error: string | null;
}

interface UserActions {
  fetchUser: (id: string) => Promise<void>;
  updateUser: (data: Partial<User>) => void;
  logout: () => void;
}

interface UserGetters {
  isAuthenticated: boolean;
  fullName: string;
}

type UserStore = UserState & UserActions & UserGetters;

const useUserStore = create<UserStore>((set, get) => ({
  // State
  user: null,
  loading: false,
  error: null,
  
  // Actions
  fetchUser: async (id) => {
    set({ loading: true, error: null });
    try {
      const user = await fetchUserAPI(id);
      set({ user, loading: false });
    } catch (error) {
      set({ error: error.message, loading: false });
    }
  },
  
  updateUser: (data) => {
    set(state => ({
      user: state.user ? { ...state.user, ...data } : null
    }));
  },
  
  logout: () => {
    set({ user: null, token: null });
  },
  
  // Getters
  get isAuthenticated() {
    return !!get().user;
  },
  
  get fullName() {
    const user = get().user;
    return user ? `${user.firstName} ${user.lastName}` : '';
  }
}));

18. Immer深入应用

18.1 Immer在状态管理中的应用

typescript
// Immer简化不可变数据更新

import produce from 'immer';
import create from 'zustand';

interface TodoState {
  todos: Todo[];
}

const useTodoStore = create<TodoState>((set) => ({
  todos: [],
  
  // 不使用Immer
  addTodoWithoutImmer: (todo) => set(state => ({
    todos: [...state.todos, todo]
  })),
  
  // 使用Immer
  addTodo: (todo) => set(
    produce((draft) => {
      draft.todos.push(todo);
    })
  ),
  
  // 复杂嵌套更新
  updateTodoTag: (todoId, tagIndex, newTag) => set(
    produce((draft) => {
      const todo = draft.todos.find(t => t.id === todoId);
      if (todo) {
        todo.tags[tagIndex] = newTag;
      }
    })
  )
}));

18.2 Immer最佳实践

typescript
const immerBestPractices = {
  适用场景: [
    '深层嵌套数据结构',
    '数组操作(push/splice)',
    '复杂对象更新',
    '多处数据修改'
  ],
  
  不适用场景: [
    '简单浅层更新',
    '性能极致要求',
    '大量数据批量更新'
  ],
  
  性能优化: [
    '避免在循环中使用produce',
    '批量更新合并为一次produce',
    '使用freeze减少produce次数'
  ]
};

// 示例
const useOptimizedStore = create((set) => ({
  items: [],
  
  // 不好的做法
  updateItemsBad: (updates) => {
    updates.forEach(update => {
      set(produce(draft => {
        const item = draft.items.find(i => i.id === update.id);
        if (item) Object.assign(item, update.data);
      }));
    });
  },
  
  // 好的做法
  updateItemsGood: (updates) => {
    set(produce(draft => {
      updates.forEach(update => {
        const item = draft.items.find(i => i.id === update.id);
        if (item) Object.assign(item, update.data);
      });
    }));
  }
}));

19. 状态持久化方案

19.1 LocalStorage持久化

typescript
// Zustand持久化中间件

import create from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';

const useStore = create(
  persist(
    (set, get) => ({
      user: null,
      settings: {
        theme: 'light',
        language: 'zh-CN'
      },
      
      setUser: (user) => set({ user }),
      updateSettings: (settings) => set(state => ({
        settings: { ...state.settings, ...settings }
      }))
    }),
    {
      name: 'app-storage',
      storage: createJSONStorage(() => localStorage),
      
      // 选择性持久化
      partialize: (state) => ({
        user: state.user,
        settings: state.settings
      })
    }
  )
);

// Redux持久化
import { configureStore } from '@reduxjs/toolkit';
import {
  persistStore,
  persistReducer,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER
} from 'redux-persist';
import storage from 'redux-persist/lib/storage';

const persistConfig = {
  key: 'root',
  version: 1,
  storage,
  whitelist: ['user', 'settings']
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER]
      }
    })
});

export const persistor = persistStore(store);

19.2 IndexedDB持久化

typescript
// 使用IndexedDB进行大数据量持久化

import create from 'zustand';
import { persist } from 'zustand/middleware';

// 自定义IndexedDB Storage
const createIndexedDBStorage = () => {
  const dbName = 'app-db';
  const storeName = 'app-store';
  
  let db: IDBDatabase;
  
  const initDB = () => new Promise<IDBDatabase>((resolve, reject) => {
    const request = indexedDB.open(dbName, 1);
    
    request.onerror = () => reject(request.error);
    request.onsuccess = () => resolve(request.result);
    
    request.onupgradeneeded = (event) => {
      const db = (event.target as IDBOpenDBRequest).result;
      if (!db.objectStoreNames.contains(storeName)) {
        db.createObjectStore(storeName);
      }
    };
  });
  
  return {
    getItem: async (key: string) => {
      if (!db) db = await initDB();
      
      return new Promise((resolve, reject) => {
        const transaction = db.transaction(storeName, 'readonly');
        const store = transaction.objectStore(storeName);
        const request = store.get(key);
        
        request.onerror = () => reject(request.error);
        request.onsuccess = () => resolve(request.result);
      });
    },
    
    setItem: async (key: string, value: any) => {
      if (!db) db = await initDB();
      
      return new Promise((resolve, reject) => {
        const transaction = db.transaction(storeName, 'readwrite');
        const store = transaction.objectStore(storeName);
        const request = store.put(value, key);
        
        request.onerror = () => reject(request.error);
        request.onsuccess = () => resolve();
      });
    },
    
    removeItem: async (key: string) => {
      if (!db) db = await initDB();
      
      return new Promise((resolve, reject) => {
        const transaction = db.transaction(storeName, 'readwrite');
        const store = transaction.objectStore(storeName);
        const request = store.delete(key);
        
        request.onerror = () => reject(request.error);
        request.onsuccess = () => resolve();
      });
    }
  };
};

// 使用IndexedDB Storage
const useDataStore = create(
  persist(
    (set) => ({
      largeDataset: [],
      setLargeDataset: (data) => set({ largeDataset: data })
    }),
    {
      name: 'large-data',
      storage: createIndexedDBStorage()
    }
  )
);

20. 状态同步策略

20.1 多Tab同步

typescript
// 使用BroadcastChannel实现多Tab状态同步

import create from 'zustand';

const createSyncedStore = (name: string, initialState: any) => {
  const channel = new BroadcastChannel(name);
  
  const store = create((set, get) => ({
    ...initialState,
    
    _sync: (state: any) => {
      set(state);
      channel.postMessage({ type: 'STATE_UPDATE', state });
    }
  }));
  
  channel.addEventListener('message', (event) => {
    if (event.data.type === 'STATE_UPDATE') {
      store.setState(event.data.state);
    }
  });
  
  return store;
};

// 使用
const useUserStore = createSyncedStore('user-store', {
  user: null,
  setUser: (user) => useUserStore.getState()._sync({ user })
});

20.2 服务端状态同步

typescript
// 使用WebSocket实现实时状态同步

import create from 'zustand';
import io from 'socket.io-client';

const useRealtimeStore = create((set, get) => {
  const socket = io('ws://localhost:3000');
  
  socket.on('state-update', (update) => {
    set(update);
  });
  
  return {
    messages: [],
    onlineUsers: [],
    
    addMessage: (message) => {
      set(state => ({
        messages: [...state.messages, message]
      }));
      socket.emit('message', message);
    },
    
    updateOnlineUsers: (users) => {
      set({ onlineUsers: users });
    }
  };
});

21. 状态调试工具

21.1 Redux DevTools集成

typescript
// Zustand集成Redux DevTools

import create from 'zustand';
import { devtools } from 'zustand/middleware';

const useStore = create(
  devtools(
    (set) => ({
      count: 0,
      increment: () => set(
        (state) => ({ count: state.count + 1 }),
        false,
        'increment'
      ),
      decrement: () => set(
        (state) => ({ count: state.count - 1 }),
        false,
        'decrement'
      )
    }),
    {
      name: 'CounterStore',
      enabled: process.env.NODE_ENV === 'development'
    }
  )
);

// Jotai DevTools
import { useAtom } from 'jotai';
import { useAtomDevtools } from 'jotai/devtools';

function Counter() {
  const [count, setCount] = useAtom(countAtom);
  useAtomDevtools(countAtom, 'count');
  
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(c => c + 1)}>+</button>
    </div>
  );
}

21.2 自定义调试工具

typescript
// 创建状态变化日志中间件

const logger = (config) => (set, get, api) => {
  return config((args) => {
    const prevState = get();
    set(args);
    const nextState = get();
    
    console.group('State Change');
    console.log('Previous:', prevState);
    console.log('Action:', args);
    console.log('Next:', nextState);
    console.groupEnd();
  }, get, api);
};

const useStore = create(
  logger((set) => ({
    count: 0,
    increment: () => set(state => ({ count: state.count + 1 }))
  }))
);

// 时间旅行调试
const timeTravelMiddleware = (config) => (set, get, api) => {
  const history = [];
  let currentIndex = -1;
  
  const wrappedSet = (args) => {
    set(args);
    const state = get();
    history.push(state);
    currentIndex++;
  };
  
  return {
    ...config(wrappedSet, get, api),
    
    undo: () => {
      if (currentIndex > 0) {
        currentIndex--;
        set(history[currentIndex]);
      }
    },
    
    redo: () => {
      if (currentIndex < history.length - 1) {
        currentIndex++;
        set(history[currentIndex]);
      }
    },
    
    canUndo: () => currentIndex > 0,
    canRedo: () => currentIndex < history.length - 1
  };
};

22. 状态测试策略

22.1 Redux测试

typescript
// Redux Slice测试

import { configureStore } from '@reduxjs/toolkit';
import counterReducer, { increment, decrement } from './counterSlice';

describe('Counter Slice', () => {
  let store;
  
  beforeEach(() => {
    store = configureStore({
      reducer: { counter: counterReducer }
    });
  });
  
  test('should handle initial state', () => {
    expect(store.getState().counter.value).toBe(0);
  });
  
  test('should handle increment', () => {
    store.dispatch(increment());
    expect(store.getState().counter.value).toBe(1);
  });
  
  test('should handle decrement', () => {
    store.dispatch(decrement());
    expect(store.getState().counter.value).toBe(-1);
  });
});

// 异步Action测试
import { fetchUser } from './userSlice';

test('should fetch user', async () => {
  const mockUser = { id: 1, name: 'John' };
  global.fetch = jest.fn(() =>
    Promise.resolve({
      json: () => Promise.resolve(mockUser)
    })
  );
  
  await store.dispatch(fetchUser(1));
  
  const state = store.getState();
  expect(state.user.data).toEqual(mockUser);
  expect(state.user.loading).toBe(false);
});

22.2 Zustand测试

typescript
// Zustand Store测试

import { renderHook, act } from '@testing-library/react';
import { useStore } from './store';

describe('Zustand Store', () => {
  test('should increment count', () => {
    const { result } = renderHook(() => useStore());
    
    act(() => {
      result.current.increment();
    });
    
    expect(result.current.count).toBe(1);
  });
  
  test('should reset count', () => {
    const { result } = renderHook(() => useStore());
    
    act(() => {
      result.current.increment();
      result.current.increment();
      result.current.reset();
    });
    
    expect(result.current.count).toBe(0);
  });
});

// 持久化测试
import { persist } from 'zustand/middleware';

test('should persist state', () => {
  const usePersistedStore = create(
    persist(
      (set) => ({
        count: 0,
        increment: () => set(state => ({ count: state.count + 1 }))
      }),
      {
        name: 'test-storage',
        storage: {
          getItem: jest.fn(),
          setItem: jest.fn(),
          removeItem: jest.fn()
        }
      }
    )
  );
  
  const { result } = renderHook(() => usePersistedStore());
  
  act(() => {
    result.current.increment();
  });
  
  expect(result.current.count).toBe(1);
});

22.3 React Query测试

typescript
// React Query测试

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { renderHook, waitFor } from '@testing-library/react';
import { useUsers } from './hooks';

describe('useUsers', () => {
  let queryClient;
  
  beforeEach(() => {
    queryClient = new QueryClient({
      defaultOptions: {
        queries: { retry: false }
      }
    });
  });
  
  const wrapper = ({ children }) => (
    <QueryClientProvider client={queryClient}>
      {children}
    </QueryClientProvider>
  );
  
  test('should fetch users', async () => {
    const mockUsers = [{ id: 1, name: 'John' }];
    
    global.fetch = jest.fn(() =>
      Promise.resolve({
        json: () => Promise.resolve(mockUsers)
      })
    );
    
    const { result } = renderHook(() => useUsers(), { wrapper });
    
    await waitFor(() => expect(result.current.isSuccess).toBe(true));
    
    expect(result.current.data).toEqual(mockUsers);
  });
  
  test('should handle error', async () => {
    global.fetch = jest.fn(() =>
      Promise.reject(new Error('Network error'))
    );
    
    const { result } = renderHook(() => useUsers(), { wrapper });
    
    await waitFor(() => expect(result.current.isError).toBe(true));
    
    expect(result.current.error).toBeDefined();
  });
});

23. 状态安全实践

23.1 防止XSS攻击

typescript
// 状态数据清理和验证

import DOMPurify from 'dompurify';

const useSafeStore = create((set) => ({
  content: '',
  
  setContent: (rawContent) => {
    // 清理HTML内容
    const cleanContent = DOMPurify.sanitize(rawContent);
    set({ content: cleanContent });
  }
}));

// 输入验证
const validateInput = (input: string): boolean => {
  // 检查SQL注入
  const sqlPattern = /(\bor\b|\band\b|union|select|insert|update|delete|drop)/i;
  if (sqlPattern.test(input)) return false;
  
  // 检查XSS
  const xssPattern = /<script|javascript:|onerror=/i;
  if (xssPattern.test(input)) return false;
  
  return true;
};

const useSecureStore = create((set) => ({
  userInput: '',
  
  setUserInput: (input) => {
    if (validateInput(input)) {
      set({ userInput: input });
    } else {
      console.error('Invalid input detected');
    }
  }
}));

23.2 敏感数据处理

typescript
// 敏感数据加密存储

import CryptoJS from 'crypto-js';

const SECRET_KEY = process.env.REACT_APP_SECRET_KEY;

const encryptData = (data: any): string => {
  return CryptoJS.AES.encrypt(
    JSON.stringify(data),
    SECRET_KEY
  ).toString();
};

const decryptData = (encrypted: string): any => {
  const bytes = CryptoJS.AES.decrypt(encrypted, SECRET_KEY);
  return JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
};

// 加密持久化
const useSecurePersistedStore = create(
  persist(
    (set) => ({
      sensitiveData: null,
      
      setSensitiveData: (data) => set({ sensitiveData: data })
    }),
    {
      name: 'secure-storage',
      storage: {
        getItem: (name) => {
          const encrypted = localStorage.getItem(name);
          return encrypted ? decryptData(encrypted) : null;
        },
        setItem: (name, value) => {
          const encrypted = encryptData(value);
          localStorage.setItem(name, encrypted);
        },
        removeItem: (name) => {
          localStorage.removeItem(name);
        }
      }
    }
  )
);

24. 状态性能监控

24.1 性能指标收集

typescript
// 状态更新性能监控

const createPerformanceMonitor = () => {
  const metrics = [];
  
  return {
    measure: (name: string, fn: Function) => {
      const start = performance.now();
      const result = fn();
      const end = performance.now();
      
      metrics.push({
        name,
        duration: end - start,
        timestamp: Date.now()
      });
      
      return result;
    },
    
    getMetrics: () => metrics,
    
    getAverageDuration: (name: string) => {
      const filtered = metrics.filter(m => m.name === name);
      if (filtered.length === 0) return 0;
      
      const sum = filtered.reduce((acc, m) => acc + m.duration, 0);
      return sum / filtered.length;
    }
  };
};

const monitor = createPerformanceMonitor();

const useMonitoredStore = create((set) => ({
  data: [],
  
  updateData: (newData) => {
    monitor.measure('updateData', () => {
      set({ data: newData });
    });
  }
}));

24.2 渲染性能追踪

typescript
// 追踪状态变化导致的渲染

import { useEffect, useRef } from 'react';

const useRenderCount = (componentName: string) => {
  const renderCount = useRef(0);
  
  useEffect(() => {
    renderCount.current++;
    console.log(`${componentName} rendered ${renderCount.current} times`);
  });
  
  return renderCount.current;
};

// 使用
function MyComponent() {
  const renderCount = useRenderCount('MyComponent');
  const data = useStore(state => state.data);
  
  return <div>Renders: {renderCount}</div>;
}

// 检测不必要的重渲染
const useWhyDidYouUpdate = (name: string, props: any) => {
  const previousProps = useRef(props);
  
  useEffect(() => {
    if (previousProps.current) {
      const allKeys = Object.keys({ ...previousProps.current, ...props });
      const changedProps = {};
      
      allKeys.forEach(key => {
        if (previousProps.current[key] !== props[key]) {
          changedProps[key] = {
            from: previousProps.current[key],
            to: props[key]
          };
        }
      });
      
      if (Object.keys(changedProps).length > 0) {
        console.log('[why-did-you-update]', name, changedProps);
      }
    }
    
    previousProps.current = props;
  });
};

25. 总结与展望

25.1 状态管理演进趋势

typescript
const trends = {
  当前趋势: [
    '轻量化: 从Redux到Zustand',
    '原子化: Recoil/Jotai细粒度管理',
    '服务端状态分离: React Query/SWR',
    'TypeScript优先: 类型安全',
    '自动优化: React Compiler'
  ],
  
  未来方向: [
    '更智能的自动优化',
    '更好的开发者体验',
    '更小的bundle大小',
    '更强的类型推导',
    'AI辅助状态管理'
  ],
  
  选型建议: [
    '小型项目: Context + useState',
    '中型项目: Zustand/Jotai + React Query',
    '大型项目: Redux Toolkit + RTK Query',
    '特殊需求: XState(状态机) / Yjs(协作)'
  ]
};

25.2 最终建议

typescript
const finalAdvice = {
  通用原则: [
    '优先使用React内置方案',
    '服务端状态用专门的库',
    '避免过度设计',
    '根据团队技术栈选择',
    '性能不是首要考虑'
  ],
  
  学习路径: [
    '1. 深入理解useState/useReducer',
    '2. 掌握Context API',
    '3. 学习一个轻量方案(Zustand)',
    '4. 了解Redux Toolkit',
    '5. 掌握React Query',
    '6. 根据需求探索其他方案'
  ],
  
  实战经验: [
    '从简单开始,逐步优化',
    '监控性能指标',
    '建立团队规范',
    '做好文档和培训',
    '持续重构和改进'
  ]
};

25.3 状态管理核心要点

  1. 没有银弹: 没有完美的方案,只有最适合的方案
  2. 分层管理: 服务端状态、全局状态、局部状态分离
  3. 性能优化: 精确订阅、选择器优化、批量更新
  4. 开发体验: TypeScript支持、DevTools、调试工具
  5. 团队协作: 统一规范、文档完善、培训到位
  6. 持续演进: 关注新技术、适时重构、保持学习

状态管理是React应用的核心,选择合适的方案并正确使用,是构建高质量应用的关键。