如何在React-Query的独立组件中访问mutate返回的数据?
如何在独立组件中获取React Query mutation的状态数据
我们可以在不同组件中通过引用相同的queryKey,从多个useQuery方法中获取数据。现在需要了解如何在独立组件中,获取由其他组件执行的mutation的success、error、data等状态数据。
执行mutate的组件
import React, { useState, useRef } from "react"; import "./App.scss"; import { postNutritionix } from "../apis/postNutritionix"; import { useMutation } from "@tanstack/react-query"; const CompPostGetData = () => { const refQuery = useRef(null); const refApiId = useRef(null); const refApiKey = useRef(null); const { error: errorMutate, mutate, data: respMutate } = useMutation({ mutationFn: postNutritionix, onSuccess: (resp) => { console.log(resp); } }); const handleSubmitQuery = (evt) => { mutate({ apiId: refApiId.current.value, apiKey: refApiKey.current.value, query: refQuery.current.value }); evt.preventDefault(); }; const errorMessage = errorMutate?.response?.data?.message; const foodNutrients = respMutate?.data?.foods?.[0] || {}; console.log(foodNutrients); return ( <section> <article> <form onSubmit={handleSubmitQuery}> <ul> <li> <label> Food: <input type="text" ref={refQuery} /> </label> </li> <li> <label> apiId: <input type="password" ref={refApiId} /> </label> </li> <li> <label> apiKey: <input type="password" ref={refApiKey} /> </label> </li> </ul> <button type="submit">Submit query</button> {errorMutate ? ( <div className="error">Error: {errorMessage}</div> ) : null} </form> </article> </section> ); };
获取mutate数据的组件
const CompGetFromMutateData = () => { // 如何从其他组件执行的mutate中获取数据 // const {data} = useMutation({ // queryKey here??? // }); };
解决方案
React Query的mutation本身没有queryKey,要跨组件共享mutation状态,推荐两种实用方式:
方式一:利用QueryClient缓存关联queryKey
在mutation执行成功后,将结果存入指定queryKey的缓存,其他组件通过useQuery监听该queryKey获取数据。
- 修改执行mutate的组件:
import { useMutation, useQueryClient } from '@tanstack/react-query'; const CompPostGetData = () => { const queryClient = useQueryClient(); const refQuery = useRef(null); const refApiId = useRef(null); const refApiKey = useRef(null); const { error: errorMutate, mutate, data: respMutate } = useMutation({ mutationFn: postNutritionix, onSuccess: (resp) => { // 将mutation结果存入指定queryKey的缓存 queryClient.setQueryData(['nutritionixData'], resp); } }); // 其余代码保持不变 };
- 修改获取数据的组件:
import { useQuery } from '@tanstack/react-query'; const CompGetFromMutateData = () => { // 通过相同queryKey获取缓存中的mutation数据 const { data, error, isSuccess } = useQuery({ queryKey: ['nutritionixData'], enabled: false, // 禁止自动触发查询,仅读取缓存 queryFn: () => Promise.resolve(null) // 空查询函数,因为我们用缓存数据 }); return ( <section> {isSuccess && data ? ( <div> <h3>营养数据</h3> <p>食物名称: {data.data.foods[0]?.food_name}</p> <p>卡路里: {data.data.foods[0]?.nf_calories}</p> </div> ) : error ? ( <div className="error">错误: {error.response?.data?.message}</div> ) : null} </section> ); };
方式二:通过Context共享mutation实例
创建React Context,将mutation的状态和方法放入Context,让子组件通过useContext直接获取。
- 创建Context和自定义Hook:
import { createContext, useContext } from 'react'; import { useMutation } from '@tanstack/react-query'; import { postNutritionix } from "../apis/postNutritionix"; const NutritionixMutationContext = createContext(null); export const NutritionixMutationProvider = ({ children }) => { const mutation = useMutation({ mutationFn: postNutritionix, onSuccess: (resp) => { console.log(resp); } }); return ( <NutritionixMutationContext.Provider value={mutation}> {children} </NutritionixMutationContext.Provider> ); }; export const useNutritionixMutation = () => useContext(NutritionixMutationContext);
- 在父组件中包裹Provider:
// 父组件示例 import { NutritionixMutationProvider } from './path-to-context'; function App() { return ( <NutritionixMutationProvider> <CompPostGetData /> <CompGetFromMutateData /> </NutritionixMutationProvider> ); }
- 修改执行mutate的组件:
import { useNutritionixMutation } from './path-to-context'; const CompPostGetData = () => { const refQuery = useRef(null); const refApiId = useRef(null); const refApiKey = useRef(null); // 从Context获取mutation实例 const { mutate, error: errorMutate, data: respMutate } = useNutritionixMutation(); // 其余代码保持不变 };
- 修改获取数据的组件:
import { useNutritionixMutation } from './path-to-context'; const CompGetFromMutateData = () => { const { data, error, isSuccess } = useNutritionixMutation(); return ( <section> {isSuccess && data ? ( <div> <h3>营养数据</h3> <p>食物名称: {data.data.foods[0]?.food_name}</p> <p>卡路里: {data.data.foods[0]?.nf_calories}</p> </div> ) : error ? ( <div className="error">错误: {error.response?.data?.message}</div> ) : null} </section> ); };
内容的提问来源于stack exchange,提问作者steve
相关产品推荐
相关产品推荐

