Apollo useLazyQuery的onCompleted回调触发两次问题求助
解决useLazyQuery的onCompleted回调触发两次问题
常见原因及对应解决方法
1. 组件重渲染导致回调重复绑定
如果组件因状态更新(比如setLoading)触发重渲染,useLazyQuery会重新初始化,导致回调重复绑定。可以用useCallback包裹onCompleted逻辑,保证函数引用稳定:
import { useCallback } from 'react'; // ... const onCompleted = useCallback((data) => { console.log('called') if (data && data.details && data.details.color === 'blue') { releaseColor(mutationArgs) } else { // setError('Unit is not on Hold.') } }, [mutationArgs]); // 按需添加依赖项 const [getComputers] = useLazyQuery(GET_COMPUTERS, { fetchPolicy: 'network-only', onCompleted, }) const handleClick = () => { setLoading(true) getComputers() }
2. 缓存更新或网络状态变化触发额外回调
即使设置了network-only,如果有其他操作(比如mutation)更新了相关缓存,或网络状态变化,可能触发查询重执行。可以关闭notifyOnNetworkStatusChange避免此类触发:
const [getComputers] = useLazyQuery(GET_COMPUTERS, { fetchPolicy: 'network-only', notifyOnNetworkStatusChange: false, onCompleted: (data) => { console.log('called') if (data && data.details && data.details.color === 'blue') { releaseColor(mutationArgs) } else { // setError('Unit is not on Hold.') } }, })
3. 检查是否重复调用getComputers
确认handleClick是否被意外触发两次(比如按钮绑定了多次事件、组件渲染时误调用)。可以用useRef记录调用次数,避免重复执行:
const callRef = useRef(0); const handleClick = () => { if (callRef.current > 0) return; callRef.current += 1; setLoading(true) getComputers() } // 查询完成后重置计数 const onCompleted = useCallback((data) => { callRef.current = 0; if (data && data.details && data.details.color === 'blue') { releaseColor(mutationArgs) } else { // setError('Unit is not on Hold.') } }, [mutationArgs]);
4. 改用useQuery控制查询时机(场景允许时)
如果不需要懒加载,用useQuery配合skip状态控制查询执行,可避免懒查询的重复回调问题:
const { refetch } = useQuery(GET_COMPUTERS, { skip: !shouldFetch, // 用状态控制是否执行查询 fetchPolicy: 'network-only', onCompleted: (data) => { if (data && data.details && data.details.color === 'blue') { releaseColor(mutationArgs) } else { // setError('Unit is not on Hold.') } }, }) const handleClick = () => { setLoading(true) refetch() }
内容的提问来源于stack exchange,提问作者beNerd
相关产品推荐
相关产品推荐

