使用RTK Query时,是否需结合createEntityAdapter做状态规范化?
RTK Query 结合 createEntityAdapter 的价值与实践
核心价值
- 状态自动同步:同一实体的所有引用会自动保持一致,比如修改某条用户数据后,所有用到该用户的组件都会实时拿到最新值,不用手动去更新多个地方的状态
- 数据访问更高效:通过
entities[id]可以直接定位到目标数据,比遍历数组查找快得多,数据量越大优势越明显 - 简化状态操作:createEntityAdapter 自带
addOne、updateOne、removeOne等方法,不用自己写复杂的 reducer 逻辑,直接调用就能维护规范化状态 - 缓存复用更合理:不同端点返回的同一实体可以共享状态,避免重复存储相同数据,减少缓存体积
结合RTK Query的实际用法
- 在响应转换中规范化数据:列表类端点返回数组后,用适配器的
setAll方法把数据转成{ids, entities}结构存在缓存里import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { createEntityAdapter } from '@reduxjs/toolkit'; const userAdapter = createEntityAdapter(); const api = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/' }), endpoints: (builder) => ({ getUsers: builder.query({ query: () => 'users', transformResponse: (response) => userAdapter.setAll(userAdapter.getInitialState(), response) }), }), }); export const { useGetUsersQuery } = api; - 自定义缓存更新逻辑:用
onQueryStarted配合适配器方法,处理增删改后的缓存同步,比如新增用户后直接更新缓存,不用重新拉取整个列表addUser: builder.mutation({ query: (user) => ({ url: 'users', method: 'POST', body: user, }), async onQueryStarted(newUser, { dispatch, queryFulfilled }) { const { data: addedUser } = await queryFulfilled; // 更新getUsers查询的缓存数据 dispatch( api.util.updateQueryData('getUsers', undefined, (draft) => { userAdapter.addOne(draft, addedUser); }) ); }, }) - 用适配器选择器获取数据:借助适配器的
selectAll、selectById等方法,快速从规范化状态中提取需要的数据const { data: usersState } = useGetUsersQuery(); // 获取所有用户数组 const allUsers = userAdapter.selectAll(usersState); // 根据ID获取单个用户 const targetUser = userAdapter.selectById(usersState, '123');
要不要花精力用这个方案?
如果你的项目符合以下场景,非常值得投入:
- 数据存在大量跨端点的重复引用(比如订单关联用户、评论关联文章)
- 需要频繁对数据进行增删改查操作
- 数据量较大,追求高效的状态访问和更新
如果只是简单的列表展示、很少有数据交互,直接用RTK Query默认的缓存机制就足够,没必要额外引入规范化。
内容的提问来源于stack exchange,提问作者AIMEUR Amin
相关产品推荐
相关产品推荐

