在 Redux Toolkit (RTK) 中,createSlice 和 createApi 都是用来生成 reducer 的,但它们的定位和功能差异很大。简单说:createSlice 是通用的状态管理工具,而 createApi 是专门为数据获取和缓存设计的增强工具。
核心区别一览
| 维度 | createSlice | createApi (RTK Query) |
|---|---|---|
| 主要用途 | 管理任何同步/异步的状态(如 UI 开关、表单数据、用户信息等) | 专门处理与服务端的数据交互(请求、缓存、轮询、乐观更新等) |
| 自动生成内容 | actions + reducer | reducer + middleware + 自动生成的 hooks(如 useXxxQuery) |
| 是否需要额外配置 | 只需编写 reducer 逻辑 | 必须在 store 中挂载自动生成的 middleware,否则缓存、重试等功能失效 |
| 状态结构 | 完全由你定义(如 { value: 0, loading: false }) | 自动生成固定的状态结构(data, error, isLoading, isFetching, isSuccess 等) |
| 请求去重/缓存 | 需要自己实现 | 开箱即用,自动处理 |
| 使用场景 | 所有 reducer 的基础 | 仅用于定义 API 端点 |
详细解析
1. createSlice:通用状态切片
// 一个简单的计数 slice
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => { state.value++ },
decrement: (state) => { state.value-- }
}
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
- 生成的 reducer 是普通函数,可以放入
configureStore的reducer字段。 - 不产生 middleware,不需要额外挂载。
- 适合管理任何非 API 相关的状态(主题、表单、本地数据等)。
2. createApi:API 专用增强版
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
const api = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (builder) => ({
getPosts: builder.query({
query: () => 'posts'
})
})
});
export const { useGetPostsQuery } = api;
export default api.reducer;
export const apiMiddleware = api.middleware; // 必须挂载的中间件
- 生成的 reducer 路径为
reducerPath(默认'api'),内部维护请求缓存、标签、订阅状态等。 - 自动生成 middleware,必须在
configureStore中调用getDefaultMiddleware().concat(apiMiddleware)挂载,否则:- 缓存永远不会过期
- 轮询/乐观更新/自动重试不工作
- 手动
invalidateTags无效
- 自动生成 hooks(如
useGetPostsQuery),可以直接在 React 组件中使用,管理加载/错误状态。
在 configureStore 中同时使用
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
import apiReducer, { apiMiddleware } from './api';
export const store = configureStore({
reducer: {
counter: counterReducer, // 普通 slice reducer
[api.reducerPath]: apiReducer // createApi 生成的 reducer
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(apiMiddleware) // 必须挂载
});
总结:什么时候用什么?
- 纯前端状态(UI 开关、表单输入、本地计数器)→ 用
createSlice。 - 从后端获取数据(REST/GraphQL 请求、缓存、轮询)→ 用
createApi(RTK Query)。 - 不要用
createApi管理普通状态,它会产生不必要的缓存开销和固定的状态结构。 - 两者可以完美共存:
createApi管理数据层,createSlice管理 UI 层。
常见误区
- ❌ 认为
createApi只是createSlice的语法糖 → 错,它是完全不同的实现,底层依赖createSlice但添加了中间件和自动缓存。 - ❌ 忘记挂载
api.middleware→ 导致请求状态不更新、缓存永不失效。 - ❌ 把普通状态(如
isModalOpen)放进createApi的 endpoints → 浪费性能,应该用createSlice。
评论