TanStack Query中getQueryData读取缓存始终返回undefined问题求助
TanStack Query useMutation 缓存读取问题解决
问题场景
调用useMutation完成登录请求并拿到预期数据后,使用getQueryData(['authData'])读取对应key的缓存始终返回undefined。
相关代码
用于创建Mutation的代码:
const axiosInstance = axios.create(habiticaAPIconf); function parseResponse(response:LoginDataContract):AuthData{ return { id: response.data.id, apiToken: response.data.apiToken, username: response.data.username } } const getAuthenticationData = async (userCredentials:UserCredentials):Promise<AuthData> => { const response = await axiosInstance.post<LoginDataContract>("/user/auth/local/login", {...userCredentials}); return parseResponse(response.data); } export function useCredentialData() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (loginData:UserCredentials):Promise<AuthData> => getAuthenticationData(loginData), mutationKey: ['authData'] }); };
触发Mutation的组件:
export function LoginForm() { const { mutate, isSuccess, data } = useCredentialData(); function handleLogin(e: MouseEvent<HTMLButtonElement, globalThis.MouseEvent>) { e.preventDefault(); mutate({ username: (document.getElementById("email") as HTMLInputElement).value, password: (document.getElementById("password") as HTMLInputElement).value }); console.log(data); // 同步调用无法拿到异步mutation的结果 } return ( <form> <label htmlFor="email"> <input type="email" name="email" id="email"></input> </label> <label htmlFor="password"> <input type="password" name="password" id="password"></input> </label> <button type="submit" onClick={ (e)=> {handleLogin(e)}}>Login</button> <span>{isSuccess ? `${data.username}` : ""}</span> </form> ) }
读取缓存的组件:
import { useQueryClient } from "@tanstack/react-query"; export function SidebarTasksList() { const queryClient = useQueryClient(); return ( <section> <button onClick={ ()=>console.log(queryClient.getQueryData(['authData'])) }>CLICK</button> </section> ); }
原因分析
useMutation的mutationKey仅用于标识mutation实例(比如跟踪状态、取消请求等),不会自动将mutation结果存入Query缓存。Query缓存的读写依赖独立的queryKey,和mutationKey是完全分离的概念,因此直接用getQueryData读取['authData']会返回undefined。
解决方案
在useMutation的onSuccess回调中,手动调用queryClient.setQueryData将mutation结果写入指定queryKey对应的缓存:
修改useCredentialData函数,新增onSuccess配置:
export function useCredentialData() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (loginData:UserCredentials):Promise<AuthData> => getAuthenticationData(loginData), mutationKey: ['authData'], // 登录成功后将数据写入Query缓存 onSuccess: (authData) => { queryClient.setQueryData(['authData'], authData); } }); };
修改完成后,mutation执行成功时,结果会被写入['authData']对应的缓存,此时SidebarTasksList组件中调用queryClient.getQueryData(['authData'])即可正确读取登录数据。
额外说明:LoginForm中的console.log(data)是同步执行的,无法拿到异步mutation的实时结果;若需要在mutation完成后处理数据,可使用mutate的回调函数或监听isSuccess状态变化。
内容的提问来源于stack exchange,提问作者jazzgot
相关产品推荐
相关产品推荐

