RTK Query同端点多mutation请求的isLoading状态单独校验方案
RTK Query多请求独立加载状态的常规处理方式
当你用单个RTK Query mutation发起多次不同请求,需要给每个请求(比如每个触发按钮)单独设置加载指示器时,常用这几种方式:
1. 手动维护请求状态映射表
用React的useState创建一个对象,以每个请求的唯一标识(比如数据ID、自定义请求key)为键,存储对应请求的加载状态。发起请求前标记为加载中,请求完成(无论成功失败)后取消标记:
import { useState } from 'react'; import { someApi } from './api'; function MyComponent() { const [makeRequest] = someApi.useMutation(); const [requestLoading, setRequestLoading] = useState({}); const handleRequest = async (data, requestKey) => { // 标记当前请求为加载中 setRequestLoading(prev => ({ ...prev, [requestKey]: true })); try { await makeRequest(data).unwrap(); // 请求成功后的逻辑 } catch (err) { // 请求失败后的错误处理 } finally { // 请求结束,取消加载状态 setRequestLoading(prev => ({ ...prev, [requestKey]: false })); } }; return ( <> <button onClick={() => handleRequest({ id: 1 }, 'req-1')} disabled={requestLoading['req-1']} > {requestLoading['req-1'] ? '加载中...' : '发起请求1'} </button> <button onClick={() => handleRequest({ id: 2 }, 'req-2')} disabled={requestLoading['req-2']} > {requestLoading['req-2'] ? '加载中...' : '发起请求2'} </button> </> ); }
这种方式简单直接,完全自定义状态跟踪,适合场景简单的需求。
2. 利用RTK Query内置的请求跟踪功能
RTK Query允许开启mutation的请求跟踪,然后通过useMutationState钩子获取所有活跃请求的状态,需要给每个请求添加唯一标识来区分:
首先在定义mutation时开启跟踪:
// api定义文件 import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; export const someApi = createApi({ reducerPath: 'someApi', baseQuery: fetchBaseQuery({ baseUrl: '/' }), endpoints: (builder) => ({ someMutation: builder.mutation({ query: (data) => ({ url: '/your-endpoint', method: 'POST', body: data, }), track: true, // 开启所有请求的状态跟踪 }), }), }); export const { useSomeMutationMutation } = someApi;
然后在组件中使用:
import { useSomeMutationMutation, someApi } from './api'; function MyComponent() { const [makeRequest] = useSomeMutationMutation(); // 获取该mutation的所有请求状态 const mutationStates = someApi.useMutationState({ endpoint: 'someMutation', }); // 发起请求时携带唯一的requestId作为meta标识 const handleRequest = (data, requestId) => { makeRequest(data, { meta: { requestId } }); }; // 判断指定请求是否处于加载中 const isRequestLoading = (requestId) => { return mutationStates.some( state => state.meta?.requestId === requestId && state.status === 'pending' ); }; return ( <> <button onClick={() => handleRequest({ id: 1 }, 'req-1')} disabled={isRequestLoading('req-1')} > {isRequestLoading('req-1') ? '加载中...' : '发起请求1'} </button> <button onClick={() => handleRequest({ id: 2 }, 'req-2')} disabled={isRequestLoading('req-2')} > {isRequestLoading('req-2') ? '加载中...' : '发起请求2'} </button> </> ); }
这种方式复用RTK Query的内置状态管理,不需要手动维护状态对象,适合需要精细控制请求状态的场景。
3. 封装独立的请求按钮组件
把每个请求按钮和对应的mutation逻辑封装成独立组件,每个组件内部单独调用useMutation,这样每个组件天然拥有独立的isLoading状态:
import { someApi } from './api'; const RequestButton = ({ data, children }) => { const [makeRequest, { isLoading }] = someApi.useMutation(); const handleClick = () => { makeRequest(data); }; return ( <button onClick={handleClick} disabled={isLoading}> {isLoading ? '加载中...' : children} </button> ); }; // 使用组件 function MyComponent() { return ( <> <RequestButton data={{ id: 1 }}>发起请求1</RequestButton> <RequestButton data={{ id: 2 }}>发起请求2</RequestButton> </> ); }
这种方式代码解耦,状态完全隔离,适合需要复用请求按钮逻辑的场景。
内容的提问来源于stack exchange,提问作者Robert Koritnik
相关产品推荐
相关产品推荐

