在 Redux Toolkit (RTK) 中,createSlicecreateApi 都是用来生成 reducer 的,但它们的定位和功能差异很大。简单说:createSlice 是通用的状态管理工具,而 createApi 是专门为数据获取和缓存设计的增强工具。

核心区别一览

维度createSlicecreateApi (RTK Query)
主要用途管理任何同步/异步的状态(如 UI 开关、表单数据、用户信息等)专门处理与服务端的数据交互(请求、缓存、轮询、乐观更新等)
自动生成内容actions + reducerreducer + 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 是普通函数,可以放入 configureStorereducer 字段。
  • 不产生 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