React Query 如何通过同一个useMutation实现并行请求独立加载状态
你当前的写法无法实现需求,核心原因是单个useMutation实例仅能跟踪一次 mutation 请求的状态,每次触发新的 mutation 会覆盖旧的状态,自然无法并行跟踪多个不同请求的加载状态。这里提供两种常用的落地方案:
方案一:抽离子组件独立维护 mutation(推荐)
将循环渲染的每一行用户项抽为单独的子组件,每个子组件内部持有独立的useMutation实例,状态天然隔离,完全支持并行请求互不影响,是最简单通用的方案。
// 抽离独立的用户行组件,每个组件维护自己的mutation状态 const UserItem = ({ entry }) => { const userMutation = useMutation({ mutationFn: async (userData) => { return await axios.post("https://reqres.in/api/users", userData); } }); const handleClick = () => { userMutation.mutate(entry); }; return ( <div> {entry.userName} <button onClick={handleClick} disabled={userMutation.isLoading}> post stuff </button> {userMutation.isLoading && <span>SPINNER</span>} </div> ) } // 父组件只需循环渲染子组件即可 const Parent = () => { return ( <> <span>parallel mutations:</span> {data.map((entry) => <UserItem key={entry.userName} entry={entry} />)} </> ) }
方案二:使用
useMutationState全局筛选状态 如果你需要在父组件统一管理所有 mutation 状态,可以用 react-query 内置的useMutationStateAPI,通过给每个请求打唯一的mutationKey标记,再按 key 筛选对应请求的状态即可。
// 定义公共mutation hook const useUserMutation = () => { return useMutation({ mutationFn: async (userData) => { return await axios.post("https://reqres.in/api/users", userData); } }) } const Parent = () => { const userMutation = useUserMutation(); const handleClick = (userData) => { // 触发请求时传入唯一mutationKey做标记 userMutation.mutate(userData, { mutationKey: ['userMutation', userData.userName] }) } return ( <> <span>parallel mutations:</span> {data.map((entry) => { // 按mutationKey筛选当前用户对应的请求状态 const [isLoading] = useMutationState({ filters: { mutationKey: ['userMutation', entry.userName], status: 'pending' }, select: (mutation) => mutation.state.isLoading }) return ( <div key={entry.userName}> {entry.userName} <button onClick={() => handleClick(entry)} disabled={isLoading}> post stuff </button> {isLoading && <span>SPINNER</span>} </div> ) })} </> ) }
两种方案按需选择即可:子组件方案逻辑简单无额外学习成本,适合绝大多数业务场景;useMutationState方案适合需要在父层聚合统计所有 mutation 状态的特殊场景。
内容的提问来源于stack exchange,提问作者Ognjen Mišić
相关产品推荐
相关产品推荐

