React Redux Toolkit 状态管理完全指南

FreeGuideOnline 最新 2026-06-12

Redux 一直是 React 生态中最流行的状态管理库之一。然而,传统的 Redux 配置繁琐、样板代码多,让许多初学者望而却步。Redux Toolkit(RTK)是 Redux 官方推荐的工具集,旨在简化 Redux 的开发流程。本教程将带你从零开始,使用 Redux Toolkit 构建可维护、可扩展的 React 应用状态。


为什么选择 Redux Toolkit?

Redux Toolkit 解决了传统 Redux 的几大痛点:

  • 配置简化:内置 configureStore,自动组合 reducer、启用 Redux DevTools 和中间件。
  • 减少样板代码:通过 createSlice 自动生成 action creator 和 action types。
  • 不可变更更新:内置 immer 库,让你以“可变”写法生成不可变状态。
  • 一体化异步处理createAsyncThunk 使异步逻辑变得清晰且类型安全。
  • 官方维护:成为 Redux 官方标准,社区资源丰富。

环境准备

确保你已经创建了一个 React 项目,例如使用 Create React App 或 Vite。然后安装所需依赖:

npm install @reduxjs/toolkit react-redux

对于 TypeScript 项目,类型声明已包含在内,无需额外安装。


核心概念速览

  • Store:应用的唯一状态树,由 configureStore 创建。
  • Slice:状态切片,包含 reducer、初始状态和自动生成的 actions。
  • Provider:React Redux 提供的包裹组件,使组件能访问 Store。
  • useSelector / useDispatch:Hooks,用于读取状态和派发 actions。

创建第一个 Slice:计数器示例

Redux Toolkit 的核心 API 是 createSlice,它将 reducer 逻辑和 actions 合为一体。

// features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
    name: 'counter',          // slice 名称,用于生成 action type
    initialState: {
        value: 0,
    },
    reducers: {
        increment: (state) => {
            state.value += 1;     // 直接修改 state,内部使用 immer 生成不可变结果
        },
        decrement: (state) => {
            state.value -= 1;
        },
        incrementByAmount: (state, action) => {
            state.value += action.payload; // action.payload 携带参数
        },
    },
});

// 自动生成的 action creators
export const { increment, decrement, incrementByAmount } = counterSlice.actions;

// 导出 reducer,用于 store 配置
export default counterSlice.reducer;

配置 Store

使用 configureStore 将所有 slice reducer 组合在一起。

// app/store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';

export const store = configureStore({
    reducer: {
        counter: counterReducer,  // 可继续添加其他 slice
    },
});

类型提示(TypeScript 可选)

// app/store.ts
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
import type { Action, ThunkAction } from '@reduxjs/toolkit';

export const store = configureStore({
    reducer: {
        counter: counterReducer,
    },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
export type AppThunk<ReturnType = void> = ThunkAction<
    ReturnType,
    RootState,
    unknown,
    Action<string>
>;

在 React 应用中集成

在入口文件中用 Provider 包裹整个应用,并传入 store。

// index.js (或 main.jsx)
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './app/store';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
        <App />
    </Provider>
);

在组件中使用 Redux 状态

// components/Counter.jsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { decrement, increment, incrementByAmount } from '../features/counter/counterSlice';

const Counter = () => {
    const count = useSelector((state) => state.counter.value);
    const dispatch = useDispatch();

    return (
        <div>
            <h2>计数器{count}</h2>
            <button onClick={() => dispatch(increment())}>增加</button>
            <button onClick={() => dispatch(decrement())}>减少</button>
            <button onClick={() => dispatch(incrementByAmount(5))}>增加 5</button>
        </div>
    );
};

export default Counter;

处理异步逻辑:createAsyncThunk

真实应用中,不少状态需要从 API 获取。createAsyncThunk 封装了异步 action 的创建,自动处理 pending、fulfilled 和 rejected 三种状态。

定义一个异步 thunk

// features/posts/postsSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';

// 异步请求
export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => {
    const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
    return response.data;   // 这个值将成为 fulfilled action 的 payload
});

const postsSlice = createSlice({
    name: 'posts',
    initialState: {
        items: [],
        status: 'idle',       // 'idle' | 'loading' | 'succeeded' | 'failed'
        error: null,
    },
    reducers: {},
    extraReducers: (builder) => {
        builder
            .addCase(fetchPosts.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(fetchPosts.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.items = action.payload;
            })
            .addCase(fetchPosts.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.error.message;
            });
    },
});

export default postsSlice.reducer;

在组件中触发异步请求

// components/PostsList.jsx
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchPosts } from '../features/posts/postsSlice';

const PostsList = () => {
    const dispatch = useDispatch();
    const posts = useSelector((state) => state.posts.items);
    const postStatus = useSelector((state) => state.posts.status);
    const error = useSelector((state) => state.posts.error);

    useEffect(() => {
        if (postStatus === 'idle') {
            dispatch(fetchPosts());
        }
    }, [postStatus, dispatch]);

    let content;

    if (postStatus === 'loading') {
        content = <p>正在加载...</p>;
    } else if (postStatus === 'succeeded') {
        content = posts.map((post) => <li key={post.id}>{post.title}</li>);
    } else if (postStatus === 'failed') {
        content = <p>{error}</p>;
    }

    return (
        <section>
            <h2>文章列表</h2>
            <ul>{content}</ul>
        </section>
    );
};

export default PostsList;

组织 Redux 状态的最佳实践

  1. 按特性划分 Slice
    将与同一功能域相关的 state、reducer、thunk 放在同一个文件夹中,便于维护。

  2. 标准化状态结构
    避免深层嵌套,推荐使用类似于数据库的标准化结构(按 ID 索引实体),便于查询和更新。

  3. 避免在 Redux 中存放所有状态
    仅将全局共享或跨组件状态放入 Redux。局部 UI 状态仍可使用 useState

  4. 使用 Selector 封装复杂读取
    简单的 state.user.name 可以直接在 useSelector 中读取,但逻辑复杂时,创建可复用的 selector 函数(或配合 reselect 库)。

  5. TypeScript 友好
    明确定义 RootStateAppDispatch 类型,在 hooks 中使用类型化版本代替原生 useDispatch / useSelector


常见模式:数据缓存与重新获取

当数据需要缓存并避免重复请求时,可在 thunk 中加入条件判断。

// features/posts/postsSlice.js
export const selectAllPosts = (state) => state.posts.items;

export const fetchPostsIfNeeded = () => (dispatch, getState) => {
    const { posts } = getState();
    if (posts.status === 'idle') {
        dispatch(fetchPosts());
    }
};

然后在组件中使用:

useEffect(() => {
    dispatch(fetchPostsIfNeeded());
}, [dispatch]);

调试与 DevTools

Redux Toolkit 默认集成了 Redux DevTools 扩展。启动应用后,打开浏览器的 DevTools 即可查看:

  • 所有分发的 actions
  • 状态变化历史
  • 时间旅行调试
  • Action、State 和 Diff 的详细视图

进一步学习方向

  • RTK Query:Redux Toolkit 内置的数据获取和缓存解决方案,让 API 状态管理自动化。
  • 与 TypeScript 深度结合:类型安全的 thunk、泛型 hooks、强类型 selectors。
  • Middleware 定制:使用 getDefaultMiddleware 自定义中间件,整合日志、持久化等需求。
  • 与 React Router 集成:通过状态控制导航守卫或共享路由参数。

总结

Redux Toolkit 是现代 React 应用状态管理的首选方案。它消除了传统 Redux 的繁琐,提供了清晰且强大的 API。通过本指南,你已经掌握了:

  • createSlice 定义状态和动作
  • configureStore 创建全局 Store
  • React 组件中使用 useSelectoruseDispatch
  • createAsyncThunk 处理异步逻辑
  • 状态结构和文件组织的最佳实践

立即动手实践,将 Redux Toolkit 应用到你的下一个项目中,体验高效的状态管理流程。