You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RTK Query中能否传入服务函数?非序列化值报错求助

解决RTK Query传入非序列化服务实例导致的状态错误

我有个需要从React Hook获取用户token的服务,无法直接在Redux Toolkit Query(RTKQ)的API定义中使用。于是尝试在调用mutation时传入该服务实例,功能可以正常运行,但会收到「状态中存在非序列化数据」的错误日志。

代码示例

Mutation定义

removeItemById: builder.mutation<void, {service: ItemService; uuid: string}>({
  invalidatesTags: ['Beneficiaries'],
  queryFn: async ({ service, uuid }) => {
    const result = await service.remove(uuid);
    return { data: result };
  },
})

组件中调用

const [remove, { isLoading, isError, isSuccess }] = useRemoveItemByIdMutation();

const handleRemove = () => {
  remove({service: itemService, uuid});
};

错误信息

A non-serializable value was detected in the state, in the path: item.queries.getItems({}).originalArgs.add
翻译:检测到状态中存在非序列化值,路径:item.queries.getItems({}).originalArgs.add

解决方法

问题根源

RTKQ会自动缓存mutation/query的调用参数(即originalArgs),而你传入的ItemService是类实例/复杂对象,属于Redux默认不允许的非序列化数据,因此触发了错误提示。

方法1:重构服务,避免传入实例

最推荐的方式是调整服务的设计,让它可以在RTKQ的queryFn内部直接调用,无需传入实例:

  1. 把服务的方法改成纯函数,将token作为参数传入
  2. 在queryFn中从Redux store获取token(如果token存在store中),再调用服务方法

示例代码:

重构后的服务

// ItemService.ts
export const removeItem = async (uuid: string, token: string) => {
  const response = await fetch(`/api/items/${uuid}`, {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });
  return response.json();
};

更新后的RTKQ Mutation

removeItemById: builder.mutation<void, string>({
  invalidatesTags: ['Beneficiaries'],
  queryFn: async (uuid, { getState }) => {
    // 从store中获取token
    const token = (getState() as RootState).auth.token;
    const result = await removeItem(uuid, token);
    return { data: result };
  },
})

组件调用简化

const [remove, { isLoading, isError, isSuccess }] = useRemoveItemByIdMutation();

const handleRemove = () => {
  remove(uuid);
};

方法2:忽略特定路径的非序列化检测(不推荐)

如果暂时无法重构服务,可以在Redux配置中忽略RTKQ缓存参数的序列化检测,治标不治本,仅作为临时方案:

export const store = configureStore({
  reducer: {
    [api.reducerPath]: api.reducer,
    // 其他reducer
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [api.util.resetApiState],
        // 忽略RTKQ的queries和mutations路径下的序列化检测
        ignoredPaths: ['item.queries', 'item.mutations'],
      },
    }).concat(api.middleware),
});

方法3:用自定义baseQuery注入token

如果服务基于fetch/axios,可以通过RTKQ的baseQuery统一注入token,无需手动传参:

const baseQuery = fetchBaseQuery({
  baseUrl: '/api',
  prepareHeaders: (headers, { getState }) => {
    const token = (getState() as RootState).auth.token;
    if (token) {
      headers.set('Authorization', `Bearer ${token}`);
    }
    return headers;
  },
});

// 之后在API定义中使用这个baseQuery
export const api = createApi({
  baseQuery,
  endpoints: (builder) => ({ /* ... */ }),
});

内容的提问来源于stack exchange,提问作者DoctorHe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 08:33:04