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

React组件外获取RTK Query数据?TypeScript类型问题求助

问题:RTK Query 跨端点自定义选择器的 TypeScript 实现

我正在开发基于 React TypeScript 的应用,使用 RTK Query,想要实现自定义选择器,但需要从另一个端点获取数据:

store.dispatch(userApiSlice.endpoints.check.initiate(undefined))
const data = userApiSlice.endpoints.check.getSomeData

export const selectCartItemsResult = cartApiSlice.endpoints.getCartItems
  .select(data?.user?.id ?? skipToken)

我找到一个解决方案示例:

class TodoService {
   getSelectorForTodo(todoId: string) {
     if (this._lastId !== todoId) 
       this._lastSelector = api.endpoints.getTodo.select( {id: todoId } )
     return this._lastSelector
   }

   getTodoTitle( todoId: string ) {
     const todo = this.getSelectorForTodo(todoId)(state)
     return todo.data.title
   }
}

但我不知道 state 变量从何处获取,尝试用 store.getState() 却出现类型错误:

const data = userApiSlice.endpoints.check
  .select(undefined)(store.getState())

报错信息:

The types of 'api.queries' are incompatible between these types.
Type 'QueryState<{ getCartItems: QueryDefinition<number, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, "cart", EntityState<...>, "api">; clearCart: MutationDefinition<...>; addItem: MutationDefinition<...>; changeItemQuantity: MutationDefinition<...>; changeItemSize: MutationDefini...' is not assignable to type 'QueryState<{ registration: MutationDefinition<IRegisterBody, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, "cart", IUserApiState, "api">; login: MutationDefinition<...>; check: QueryDefinition<...>; }>'.

补充说明:cartApiSlice 和 userApiSlice 是通过 injectEndpoints 创建的。

需要一个能通过 TypeScript 编译、正确声明 state 变量的示例。


解决方案

1. 导出统一的 RootState 类型

首先从 store 文件导出正确的全局状态类型,这是解决类型不兼容的核心:

// store.ts
import { configureStore } from '@reduxjs/toolkit'
import { baseApi } from './services/baseApi' // 你的基础 API 切片(所有 injectEndpoints 基于此扩展)

export const store = configureStore({
  reducer: {
    [baseApi.reducerPath]: baseApi.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(baseApi.middleware),
})

// 导出全局状态类型
export type RootState = ReturnType<typeof store.getState>

2. 创建跨端点的组合选择器

用 createSelector 组合两个端点的选择器,避免直接硬编码调用 store.getState():

import { createSelector } from '@reduxjs/toolkit'
import { skipToken } from '@reduxjs/toolkit/query/react'
import { userApiSlice } from './userApi'
import { cartApiSlice } from './cartApi'
import type { RootState } from '../store'

// 第一步:获取用户校验接口的缓存数据
const selectUserCheckData = userApiSlice.endpoints.check.select(undefined)

// 第二步:组合选择器,根据用户ID获取对应购物车数据
export const selectCartItemsByUser = createSelector(
  (state: RootState) => selectUserCheckData(state),
  (userResult) => {
    const userId = userResult.data?.user?.id
    // 无用户ID时返回 skipToken,让RTK Query跳过请求
    return cartApiSlice.endpoints.getCartItems.select(userId ?? skipToken)
  },
  // 第三步:最终获取购物车数据
  (_, cartSelector) => cartSelector(store.getState())
)

3. 组件中使用选择器

在 React 组件中结合 useSelector 和 RTK Query 的 hooks 使用:

import { useSelector, useEffect } from 'react-redux'
import { useLazyQuery } from '@reduxjs/toolkit/query/react'
import { userApiSlice } from './userApi'
import { selectCartItemsByUser } from './selectors'
import type { RootState } from '../store'

function CartComponent() {
  const [triggerUserCheck] = useLazyQuery(userApiSlice.endpoints.check)
  const cartResult = useSelector((state: RootState) => selectCartItemsByUser(state))

  // 组件挂载时触发用户校验
  useEffect(() => {
    triggerUserCheck()
  }, [triggerUserCheck])

  if (cartResult.isLoading) return <div>加载中...</div>
  if (cartResult.error) return <div>加载失败</div>

  return (
    <div className="cart-items">
      {cartResult.data?.map(item => (
        <div key={item.id}>{item.name} × {item.quantity}</div>
      ))}
    </div>
  )
}

4. 类型错误原因说明

你之前遇到的类型不匹配,是因为单个 API 切片的选择器默认只识别自身切片的状态结构,而全局 RootState 包含所有扩展后的 API 状态。通过统一导出 RootState 并在选择器中明确指定,就能让 TypeScript 正确推断跨切片的状态类型。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 05:46:05