React中使用RTK Query实现链式HTTP请求的正确方案是什么?
RTK Query 实现链式HTTP请求的两种主流方案
方案1:使用skip或skipToken控制请求触发(推荐,改动最小)
RTK Query 所有内置的查询Hook都支持请求跳过逻辑,不需要条件调用Hook,也不需要拆分组件,完全符合React Hook规则。
你只需要在顶层正常调用两个Hook,通过配置控制第二个请求在draftGroupId就绪后再发起即可,原来的extraReducers处理逻辑完全不需要修改。
代码示例:
import { skipToken } from '@reduxjs/toolkit/query/react' const YourComponent = ({ contestId, ...props }) => { // 第一个请求正常触发 useGetContestByIdQuery(contestId); // 从自定义Redux状态中拿draftGroupId(和你原来的逻辑一致) const { draftgroupId, gameTypeId } = useSelector(getCurrentDraftState).contest; // 第二个请求用skipToken控制,draftGroupId不存在时自动跳过请求 useGetDraftGroupByIdQuery(draftgroupId ?? skipToken, gameTypeId); const players = useSelector(getAllPlayers); if (!draftgroupId || !players) return null; return <ActualGameScreen {...props} />; };
两种控制跳过的方式区别:
skip参数:适合需要额外自定义判断条件的场景,比如除了参数存在还要判断其他状态,写法为useGetDraftGroupByIdQuery(draftgroupId, { skip: !draftgroupId })skipToken:RTK Query 官方推荐写法,类型推导更精准,只要参数为skipToken就自动跳过请求,代码更简洁。
方案2:封装链式请求为独立Endpoint(适合多组件复用场景)
如果这个链式请求逻辑需要在多个组件中复用,可以直接在RTK Query的Api定义层把两个请求的逻辑封装成一个独立的查询Endpoint,组件层只需要调用一个Hook,不需要关心内部的请求顺序。
代码示例:
// 你的RTK Query Api Slice 定义 import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' export const contestApi = createApi({ reducerPath: 'contestApi', baseQuery: fetchBaseQuery({ baseUrl: '/api' }), endpoints: (builder) => ({ getContestById: builder.query({ query: (id) => `/contest/${id}` }), getDraftGroupById: builder.query({ query: (id) => `/draft-group/${id}` }), // 封装好的链式查询接口 getContestFullInfo: builder.query({ async queryFn(contestId, { dispatch }) { // 先拉取赛事信息 const contestRes = await dispatch( contestApi.endpoints.getContestById.initiate(contestId) ).unwrap() // 拿到draftGroupId后拉取draft组信息 await dispatch( contestApi.endpoints.getDraftGroupById.initiate(contestRes.draftGroupId) ).unwrap() return { data: contestRes } } }) }), }) // 导出自动生成的Hook export const { useGetContestFullInfoQuery } = contestApi
组件层调用:
const YourComponent = ({ contestId, ...props }) => { // 直接调用封装好的Hook,不需要处理链式逻辑 useGetContestFullInfoQuery(contestId) const players = useSelector(getAllPlayers) if (!players) return null return <ActualGameScreen {...props} /> }
你原来拆分组件的方案本身也是RTK Query官方推荐的合法写法,只是对于单组件内的简单链式请求,用第一种方案可以减少不必要的组件拆分,代码更简洁。
内容的提问来源于stack exchange,提问作者Jonathan Tuzman
相关产品推荐
相关产品推荐

