ApolloClient:组件卸载时useLazyQuery在清理副作用中未触发
组件卸载时调用useLazyQuery无响应的解决方案
问题本质
组件卸载时,useLazyQuery关联的React上下文和Apollo内部绑定已被销毁,此时调用hook返回的查询函数,无法触发网络请求——这就是你遇到的closeConnection调用后无网络日志、onCompleted/onError不执行的核心原因。
修复思路与实现
方案1:直接使用Apollo Client实例发起请求(推荐)
跳过useLazyQuery hook,直接通过Apollo Client实例调用查询/突变,因为客户端实例不依赖组件生命周期,即使组件卸载也能正常发起请求。
代码示例:
import { useApolloClient } from '@apollo/client'; const YourComponent = () => { const client = useApolloClient(); const connectionRef = React.useRef(null); React.useEffect(() => { return () => { if (connectionRef.current !== null) { console.log("closing connection ..."); const id = connectionRef.current.id; connectionRef.current = null; // 直接用客户端实例发起请求 client.query({ query: closeConnectionQuery, variables: { id }, }) .then(() => { console.log("ON COMPLETED"); }) .catch((error) => { console.log("ERROR:", error); }); } }; }, [client]); // 依赖client确保实例有效 // 其他组件逻辑... };
方案2:延迟组件卸载(备选)
如果必须使用useLazyQuery,可以通过状态控制组件延迟卸载,直到请求完成(需要父组件配合)。
子组件代码:
const ChildComponent = ({ onUnmountComplete }) => { const [isUnmounting, setIsUnmounting] = React.useState(false); const [closeConnection] = useLazyQuery(closeConnectionQuery); const connectionRef = React.useRef(null); React.useEffect(() => { return () => { if (connectionRef.current !== null && !isUnmounting) { setIsUnmounting(true); const id = connectionRef.current.id; connectionRef.current = null; closeConnection({ variables: { id }, onCompleted: () => { console.log("ON COMPLETED"); onUnmountComplete(); }, onError: (error) => { console.log("ERROR:", error); onUnmountComplete(); }, }); } }; }, [isUnmounting, onUnmountComplete]); // 其他组件逻辑... };
父组件代码:
const ParentComponent = () => { const [showChild, setShowChild] = React.useState(true); const handleUnmountComplete = () => { setShowChild(false); }; return showChild ? ( <ChildComponent onUnmountComplete={handleUnmountComplete} /> ) : null; };
该方案缺点是组件会在卸载前短暂停留,可能影响用户体验,仅作为无法使用方案1时的备选。
补充说明
如果closeConnection是用于修改服务器状态(比如关闭连接),更合理的做法是使用Mutation而非Query,此时只需将方案1中的client.query()替换为client.mutate()即可,逻辑完全一致。
内容的提问来源于stack exchange,提问作者Maxime JENNY
相关产品推荐
相关产品推荐

