React中使用useLazyQuery后signType12状态重置为初始值的问题
问题:设置signType12后,useLazyQuery的onCompleted回调中该值变回初始null
点击按钮将signType12设置为url或email后,useEffect会触发调用useLazyQuery对应的API,但在useLazyQuery的onCompleted回调中,signType12却变成了初始值null。
相关代码
业务逻辑代码
const [getOrder] = useLazyQuery(GET_BUSINESS_LIFE_ORDER, { fetchPolicy: "no-cache", onError: useCallback((err: any) => { apiErrorHandler(err); setIsTransLoading(false); }, []), onCompleted: useCallback(({ getBusinessLifeOrder }: any) => { setLifeOrder(getBusinessLifeOrder); setLoading(false); console.log(signType12, "sign12"); if (getBusinessLifeOrder.signatureId) { getOrderSignatureInfo({ variables: { id: orderId, }, }); } else if (signType12 != null) { companySignDoc({ variables: { orderId: orderId, deliveryMethod: signType12 == "url" ? "URL" : signType12 == "email" ? "EMAIL" : null, userType: "LEGALREPRESENTATIVE", signer1: { name: getBusinessLifeOrder.contactInfo.name, email: getBusinessLifeOrder.contactInfo.email, }, }, }); } // setIsTransLoading(false); }, []), }); useEffect(() => { if (signType12) { console.log(signType12, "sign12"); // setIsTransLoading(true); getOrder({ variables: { id: orderId } }); } }, [signType12]);
按钮交互代码
<button onClick={() => { setSignType12('url') }}> Assinar agora </button> <button onClick={() => { setSignType12('email') }}> Enviar documento por email </button>
问题原因
这是闭包导致的 stale 值问题:onCompleted回调通过useCallback包裹,但依赖项数组是空的,所以它捕获的是组件初始化时signType12的初始值(null)。即使后续signType12被更新,回调里依然只能访问到最初捕获的那个值。
解决方案
方案1:更新useCallback的依赖项
把signType12和orderId(如果orderId也会动态变化)加入useCallback的依赖数组,确保回调能获取到最新的变量值:
onCompleted: useCallback(({ getBusinessLifeOrder }: any) => { // 原有逻辑保持不变 }, [signType12, orderId]),
方案2:调用getOrder时传递signType12
如果不想依赖外部变量的更新,也可以在调用getOrder时把signType12作为自定义上下文参数传递,在onCompleted中直接从上下文获取:
// 在useEffect中调用getOrder时传递参数 useEffect(() => { if (signType12) { getOrder({ variables: { id: orderId }, context: { currentSignType: signType12 } }); } }, [signType12]); // 在onCompleted中获取传递的参数 onCompleted: useCallback(({ getBusinessLifeOrder }: any, { context }) => { const signType12 = context.currentSignType; // 后续逻辑使用获取到的signType12即可 }, []),
注意事项
- 方案1中,依赖项更新后,React会在
signType12或orderId变化时重新创建onCompleted回调,确保能拿到最新值。 - 方案2需要确认你的GraphQL客户端支持通过
context传递自定义参数(Apollo Client原生支持该特性)。
内容的提问来源于stack exchange,提问作者Rahul Kumar Singh
相关产品推荐
相关产品推荐

