React状态管理方案深度对比:Zustand vs Jotai vs Redux Toolkit,2025年选型指南

By | 2026年6月9日

引言

在React生态中,状态管理一直是核心话题。随着React 18和Server Components的普及,传统方案如Redux面临挑战,而轻量级方案Zustand和Jotai逐渐成为新宠。本文将从实际开发角度,对比这三种方案在2025年的适用场景。

背景:为什么需要状态管理?

React的useState和useContext适合小型应用,但当状态需要跨组件共享、持久化或复杂异步逻辑时,专用状态管理库能显著提升开发效率。

方案概览

| 特性 | Zustand | Jotai | Redux Toolkit | |——|———|——-|—————| | 核心概念 | 单一store | 原子状态 | 单一store + reducer | | 学习曲线 | 低 | 中 | 高 | | 体积 | ~1KB | ~2KB | ~12KB | | TypeScript支持 | 优秀 | 良好 | 优秀 | | 中间件生态 | 有限 | 有限 | 丰富 |

实战对比

1. 计数器示例

Zustand


import { create } from 'zustand';

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

function Counter() {
  const { count, increment, decrement } = useCounterStore();
  return (
    <div>
      <h1>{count}</h1>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
}

Jotai


import { atom, useAtom } from 'jotai';

const countAtom = atom(0);

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

Redux Toolkit


import { configureStore, createSlice } from '@reduxjs/toolkit';
import { Provider, useDispatch, useSelector } from 'react-redux';

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => { state.value += 1; },
    decrement: (state) => { state.value -= 1; },
  },
});

const store = configureStore({ reducer: counterSlice.reducer });

function Counter() {
  const count = useSelector((state) => state.value);
  const dispatch = useDispatch();
  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => dispatch(counterSlice.actions.increment())}>+</button>
      <button onClick={() => dispatch(counterSlice.actions.decrement())}>-</button>
    </div>
  );
}

// App需包裹Provider
function App() {
  return (
    <Provider store={store}>
      <Counter />
    </Provider>
  );
}

2. 异步操作(API请求)

Zustand


import { create } from 'zustand';

const useUserStore = create((set) => ({
  user: null,
  loading: false,
  fetchUser: async (id) => {
    set({ loading: true });
    const res = await fetch(`/api/users/${id}`);
    const user = await res.json();
    set({ user, loading: false });
  },
}));

Jotai (使用atomWithQuery)


import { atom } from 'jotai';
import { atomWithQuery } from 'jotai/query';

const userIdAtom = atom(1);
const userAtom = atomWithQuery((get) => ({
  queryKey: ['user', get(userIdAtom)],
  queryFn: async ({ queryKey: [, id] }) => {
    const res = await fetch(`/api/users/${id}`);
    return res.json();
  },
}));

Redux Toolkit (createAsyncThunk)


import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

export const fetchUser = createAsyncThunk('user/fetch', async (id) => {
  const res = await fetch(`/api/users/${id}`);
  return res.json();
});

const userSlice = createSlice({
  name: 'user',
  initialState: { user: null, status: 'idle' },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUser.pending, (state) => { state.status = 'loading'; })
      .addCase(fetchUser.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.user = action.payload;
      });
  },
});

3. 性能优化

Zustand:自动细粒度更新

Zustand默认使用引用相等性检查,当组件只订阅部分状态时,不相关状态变化不会触发重渲染。


// 组件只订阅count,其他状态变化不会导致重渲染
const count = useCounterStore((state) => state.count);

Jotai:原子级更新

每个atom独立,只有依赖的atom变化才更新组件。

Redux Toolkit:需要手动选择

使用useSelector时需注意,默认浅比较,可结合createSelector做记忆化。


import { createSelector } from '@reduxjs/toolkit';
const selectUser = createSelector([state => state.user], user => user);

选型建议

  • 小型项目或微前端:优先Zustand,零模板代码,API简洁,TypeScript友好。
  • 需要精细控制渲染:Jotai的原子模型适合大型应用,避免不必要的重新渲染。
  • 大型项目或团队协作:Redux Toolkit生态成熟,中间件丰富,但需注意学习成本。
  • 服务端渲染(SSR):Zustand和Jotai支持良好,Redux需额外配置。

常见坑与最佳实践

  1. Zustand:避免在store外修改状态,使用getState()需谨慎。

javascript // 不推荐 const store = useCounterStore.getState(); store.count = 10; // 不会触发更新

  1. Jotai:派生原子注意依赖追踪,避免循环依赖。
  2. Redux Toolkit:不要直接修改state(Immer内部处理,但需遵循reducer纯函数原则)。

总结

没有银弹,选择取决于项目规模、团队经验和性能要求。Zustand适合快速开发,Jotai适合精细控制,Redux Toolkit适合大型企业级应用。建议小型项目先用Zustand,遇到性能瓶颈再考虑迁移。

延伸阅读

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注