父组件props状态更新时,如何重渲染React组件并重取Apollo查询?
解决方案
核心问题原因
- 渲染时直接执行副作用(修改状态、调用refetch)不符合React执行逻辑,会导致渲染异常
- Apollo默认缓存策略优先读取旧缓存,登录后请求默认复用了之前未登录时的缓存结果
- 之前useEffect无限循环大概率是依赖数组包含了会在effect执行时变化的变量,而非稳定引用的变量
修复后的完整代码
import React, { useEffect } from 'react'; import { useQuery } from "@apollo/client"; import { ME } from "../../api/authentication/me"; import LogoutButton from "../authentication/authentication-required/logout-button"; const Nav = ({ userIsAuthenticated }) => { const { data, loading, error, refetch } = useQuery(ME, { // 未登录时跳过查询,避免生成无效缓存 skip: !userIsAuthenticated, // 强制请求后端接口,不走本地旧缓存 fetchPolicy: "network-only" }); // 仅在登录状态变为true时触发重查,不会产生无限循环 useEffect(() => { if (userIsAuthenticated) { refetch(); } }, [userIsAuthenticated, refetch]); if (loading) return "User is loading..."; if (error) console.log(error); return ( <div className="Nav"> <br /> { JSON.stringify(data, null, 2) } <br /> <LogoutButton/> </div> ) }
关键修改说明
- 新增
skip: !userIsAuthenticated配置:未登录时不执行ME查询,避免产生无效缓存,也减少无用请求 - 新增
fetchPolicy: "network-only"配置:强制每次查询都请求后端接口,不走本地缓存,确保拿到最新的登录用户数据 - 用
useEffect监听userIsAuthenticated变化:只有登录状态切换为true时才触发refetch,依赖数组仅放入稳定引用的userIsAuthenticated和refetch,不会产生无限循环 - 移除了渲染流程中的状态修改和冗余的setTimeout逻辑,符合React执行规范
- 修正了原代码中
useQuery返回值的错误拼写:原errors应为error
额外排查点
如果修改后仍不生效,请检查Apollo客户端的请求拦截器配置,确认用户登录成功后,后续的ME请求已经携带了正确的身份凭证(token),如果请求头未携带登录凭证,接口仍会返回未登录状态的结果。
内容的提问来源于stack exchange,提问作者Bravo2bad
相关产品推荐
相关产品推荐

