RTK Query:如何让加载组件在mutation与标签触发的refetch完成前持续显示
RTK Query:优化mutation触发依赖请求的加载状态追踪
问题场景
点击"Add album"按钮执行createAlbum mutation后,该mutation会通过标签失效机制自动触发fetchAlbums的refetch请求。但无法直接在handleCreateAlbum中等待这个refetch完成,当前使用了复杂的逻辑表达式控制加载组件显示,希望找到更优雅的方案。
现有实现代码
按钮组件
<button onClick={handleCreateAlbum} className="border-slate-700 border-2 px-4 py-1 mb-3 transition hover:bg-green-400 rounded-lg">Add album</button>
点击处理函数
const handleCreateAlbum = () => { createAlbum(user) }
API切片配置
createAlbum: builder.mutation<IAlbum, IUser>({ invalidatesTags: (result, error, user) => { return [{ type: 'Album', id: user.id }] }, query: (user) => ({ url: '/albums', method: 'POST', body: { userId: user.id, name: faker.commerce.productName() } }) }), fetchAlbums: builder.query<IAlbum[], IUser>({ providesTags: (result, error, user) => { return [{ type: 'Album', id: user.id }] }, query: (user) => ({ url: 'albums', method: 'GET', params: { userId: user.id } }) })
当前加载状态判断
const { data, error, isLoading, isFetching } = useFetchAlbumsQuery(user); const [createAlbum, { isLoading: albumIsLoading }] = useCreateAlbumMutation(); {(!isLoading && isFetching) || albumIsLoading && <Spinner />}
优化方案
方案1:使用useIsFetching钩子统一追踪请求状态
RTK Query内置的useIsFetching钩子可以全局或针对特定端点/标签追踪所有正在进行的请求,包括mutation自动触发的refetch。
import { useIsFetching } from '@reduxjs/toolkit/query/react'; // 追踪所有正在进行的请求 const isAnyRequestLoading = useIsFetching(); // 或精准追踪目标端点的请求 const isTargetLoading = useIsFetching({ predicate: (query) => query.endpoint === 'fetchAlbums' || query.endpoint === 'createAlbum' }); // 直接根据状态显示加载组件 {isTargetLoading > 0 && <Spinner />}
优势:无需手动维护多个状态变量,完全利用RTK Query内置能力,代码简洁不易出错。
方案2:手动触发refetch并等待完成
放弃自动标签失效机制,在mutation的执行流程中手动调用fetchAlbums的refetch,通过本地状态管理加载过程。
import { useState } from 'react'; const { data, refetch } = useFetchAlbumsQuery(user); const [createAlbum] = useCreateAlbumMutation(); const [isSubmitting, setIsSubmitting] = useState(false); const handleCreateAlbum = async () => { setIsSubmitting(true); try { // 等待mutation完成 await createAlbum(user).unwrap(); // 等待refetch完成 await refetch(); } catch (error) { // 处理请求错误 console.error('请求失败:', error); } finally { setIsSubmitting(false); } }; // 根据本地状态显示加载组件 {isSubmitting && <Spinner />}
优势:精准控制请求顺序,可在所有请求完成后执行额外逻辑;劣势:需要手动管理流程,失去RTK Query自动标签失效的便利性。
方案3:优化现有状态判断逻辑
如果不想改动核心请求逻辑,可将复杂条件提取为语义化变量,提升代码可读性。
const { isLoading, isFetching } = useFetchAlbumsQuery(user); const [createAlbum, { isLoading: albumIsLoading }] = useCreateAlbumMutation(); // 语义化变量清晰表达状态含义 const isMutationInProgress = albumIsLoading; const isRefetchingAlbums = !isLoading && isFetching; const shouldShowSpinner = isMutationInProgress || isRefetchingAlbums; {shouldShowSpinner && <Spinner />}
优势:最小改动现有代码,通过语义化变量让状态判断逻辑更易理解。
内容的提问来源于stack exchange,提问作者juniorsenior
相关产品推荐
相关产品推荐

