首页 > 解决方案 > 取消所有订阅和不使用useEffect的异步任务,必须在handleSubmit

问题描述

我有这个错误,我已经通过包括stackoverflow在内的各种互联网页面不知疲倦地搜索不同的解决方案,但我找不到适用于我的案例的解决方案,

我会尽可能的总结,以免话题扩展太多,直奔主题,只希望能找到能帮助我的人

我使用 Stepper 库对步骤进行排序

问题是,在步骤 3 中使用从 Stripe 文档中提取的代码创建付款方式,异步调用与 await 一起使用,这是产生错误的原因,当我转到步骤 4 时,我显示了一个新组件,然后我消失了步骤 3 的组件,当我这样做时,我收到错误消息,我正在尝试更新不再存在的组件中的状态,但是此刻我更新我的 Stepper 状态以将我带到最后一步,II不要再做任何状态更新,我仍然收到消息并看到导致此问题的是等待调用,它要求我在移动到新组件之前清理所有订阅和异步任务,所以我需要知道如何清理这个异步调用?

在第3步应该说验证卡数据表单的字段以及开始创建支付方式的整个过程是在一个按钮调用的handleSubmit函数中完成的,,这就是为什么解决方案或使用 useEffect 的异步调用不适用于我的情况,我需要一种方法来直接在同一个 handleSubmit 中清理所有内容

在这里我留下我的总结代码:

全局状态常量,在这里我创建了我的 Stepper 状态:

here delete code of several state variables, just leave the state variables of the stepper when state change updating on a number


const useStateGlobal = () => {
    const [steps] = useState(
        [{
            title: 'Confirmar Compra',
            href: 'http://example1.com',
            onClick: (e) => {
                e.preventDefault()
                console.log('onClick', 1)
            }
        }, {
            title: 'Seleccionar tipo de pago',
            href: 'http://example2.com',
            onClick: (e) => {
                e.preventDefault()
                console.log('onClick', 2)
            }
        }, {
            title: 'Detalles de pago',
            href: 'http://example3.com',
            onClick: (e) => {
                e.preventDefault()
                console.log('onClick', 3)
            }
        }, {
            title: 'Compra Finalizada',
            href: 'http://example4.com',
            onClick: (e) => {
                e.preventDefault()
                console.log('onClick', 4)
            }
        }]
    );

    const [currentStep, setCurrentStep] = useState(0);
   
    return {
        steps,
        currentStep,setCurrentStep
    }
};

现在这是 Stepper 组件:

export const Confirmar_Paquete_Stepper = () => {  
        
        const { steps, currentStep, setCurrentStep } = useBetween(useStateGlobal);
        const buttonStyle = { background: '#E0E0E0', width: 200, padding: 16, textAlign: 'center', 
        margin: '0 auto', marginTop: 32 };

        const onClickNext = (e) => {           
            let valor = (currentStep == null || currentStep == 0 )  ? 1 : currentStep+1;           
            setCurrentStep(valor);
        }

         const onClickBack = (e) => {
             let valor = (currentStep == null || currentStep == 0) ? 1 : currentStep - 1;
             setCurrentStep(valor);
         }

        if (currentStep == 0) {
        return (           
               <div id="contenedor-stepper-compra-paquete"> 
                   <Stepper steps={steps} activeStep={currentStep}  />
                <Confirmar_Paquete />
               </div>
        );
        }
        else if (currentStep == 1) {
        return (
               <div id="contenedor-stepper-compra-paquete">
                   <Stepper steps={steps} activeStep={currentStep} />
                   <Seleccionar_Tipo_Pago_Paquete />     
                <div style={buttonStyle} onClick={onClickBack}>Volver</div>
               </div>
        );
        } else if (currentStep == 2) {
            return (
                <div id="contenedor-stepper-compra-paquete">
                    <Stepper steps={steps} activeStep={currentStep}  />

                  these are the components that create the inputs of the card number, expiration 
                  date, cvc and process and create the card payment method with the Stripe library

                    <Elements stripe={stripePromise}>
                        <CheckoutForm2/>
                    </Elements>
                    <div style={buttonStyle} onClick={onClickBack}>Volver</div>
                </div>
        );
        }   
          else if (currentStep == 3) {
              return (
                  <div id="contenedor-stepper-compra-paquete">
          
                      <Stepper steps={steps} activeStep={currentStep}  />
                      <Finalizar_Compra_Paquete />
                      <div style={buttonStyle} onClick={onClickBack}>Volver</div>
                  </div>
            );
        }  
};

现在是 CheckoutForm2 组件

 const CheckoutForm2 = () => {    
    const { steps, currentStep, setCurrentStep, token, datos_paquete_seleccionado, setDatos_paquete_seleccionado, camposDatosTarjeta, setcamposDatosTarjeta, formErrors, setformErrors, errores_servTarjeta, seterrores_servTarjeta,
            paseValidacionFormTitularTarjeta, setpaseValidacionFormTitularTarjeta,
            paseValidacionFormCorreoTarjeta, setpaseValidacionFormCorreoTarjeta,
            paseValidacionFormTarjeta, setpaseValidacionFormTarjeta,
            paseValidacionFormFechaExpTarjeta, setpaseValidacionFormFechaExpTarjeta,
            paseValidacionFormCvcTarjeta, setpaseValidacionFormCvcTarjeta,
            paseValidacionFormCiudadTarjeta, setpaseValidacionFormCiudadTarjeta,
        paseValidacionFormCodigoPostalTarjeta, setpaseValidacionFormCodigoPostalTarjeta
       } = useBetween(useStateGlobal);
    const stripe = useStripe();
    const elements = useElements();
    const titularTarjetaRegex = RegExp(
        /^[A-Za-z\s]+$/
    );
    const emailRegex = RegExp(
        /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
    );
    const codigopostalTarjetaRegex = RegExp(
        /^[0-9]+$/
    );
    const ciudadTarjetaRegex = RegExp(
        /^[A-Za-z]+$/
    );

    
    useEffect(() => {
        return () => {
            
        };
    }, []);

    const HandleValidar = async (event) => {
          Here I have code only to validate the form fields by OnChange, I have deleted it because they 
          are not important
    }

    const handleSubmit = async (event) => {
       
        event.preventDefault();        
        const { titular_tarjeta, correo_tarjeta, ciudad_tarjeta, codigo_postal_tarjeta } = event.target;  
        
Here I leave only an example of how valid each field of my form when I click directly on handleSubmit by onClick,

        //TITULAR TARJETA
        if (titular_tarjeta.value.length < 3) {           
            setformErrors(prevState => ({ ...prevState, titular_tarjeta: "Ingrese mínimo 3 caracteres"
         }));
            seterrores_servTarjeta(prevState => ({ ...prevState, titular_tarjeta: "" }));
            setpaseValidacionFormTitularTarjeta("NO");            
        }
        else if (!titularTarjetaRegex.test(titular_tarjeta.value)) {            
            setformErrors(prevState => ({ ...prevState, titular_tarjeta: "Formato de nombres inválido" 
         }));
            seterrores_servTarjeta(prevState => ({ ...prevState, titular_tarjeta: "" }));
            setpaseValidacionFormTitularTarjeta("NO");
            
        }
        else if (titular_tarjeta.value.length > 22) {
            setformErrors(prevState => ({ ...prevState, titular_tarjeta: "Ingrese maximo 22 caracteres" 
        }));
            seterrores_servTarjeta(prevState => ({ ...prevState, titular_tarjeta: "" }));
            setpaseValidacionFormTitularTarjeta("NO");
        }
        else {
            setformErrors(prevState => ({ ...prevState, titular_tarjeta: "" }));
            seterrores_servTarjeta(prevState => ({ ...prevState, titular_tarjeta: "" }));
            setpaseValidacionFormTitularTarjeta("SI");            
        }

        

        if (!stripe || !elements) {
            // Stripe.js has not yet loaded.
            // Make sure to disable form submission until Stripe.js has loaded.
            return;
        }
        
        Here I validate through a set of each state that all the fields have been completed and validated 
        correctly to just start creating the payment


        if (paseValidacionFormTitularTarjeta == "SI" && paseValidacionFormCorreoTarjeta == "SI" && paseValidacionFormTarjeta == "SI" && paseValidacionFormFechaExpTarjeta == "SI" && paseValidacionFormCvcTarjeta == "SI" && paseValidacionFormCiudadTarjeta == "SI" && paseValidacionFormCodigoPostalTarjeta == "SI")
        {    
            const cardElement = elements.getElement(CardNumberElement);

            const { error, paymentMethod } = await stripe.createPaymentMethod({
                type: 'card',
                card: cardElement,
                billing_details: {
                    email: camposDatosTarjeta.correo_tarjeta,
                    name: camposDatosTarjeta.titular_tarjeta,
                    address: {
                        city: camposDatosTarjeta.ciudad_tarjeta,
                        country: 'PE',
                        postal_code: camposDatosTarjeta.codigo_postal_tarjeta,
                    }
                },               
            });

            if (error) {                
            } 
            else 
            {     

This is where the moment I update the Stepper to number 3, which would be the last step ,, is when the error appears ,,,
the one that causes this error is the await ,,, since if I delete all that code above the await stripe the error does not appear anymore ,,, then I want to know how to clean the asynchronous tasks before moving to a new component, everything must be performed in my function by handlesubmit
     
               setCurrentStep(3);                   
            }
        }
    };

    return (
        <div id="contenedor-detalles-tarjeta">
            <Container component="main" maxWidth="md" justify="center">
                <label className="detalles-tarjeta-titulo">
                <Typography >
                    <span >Detalles de tarjeta</span>
                </Typography>
            </label>
            <form id="realizar-pago-visa" onSubmit={handleSubmit} noValidate>

           Here I have deleted all the code of the creation of the fields of the payment form, I have 
           only left the handleSubmit button

         <Button type="submit" className="confirmar-orden" name="confirmar_orden" disabled= 
         {!stripe} variant="contained" color="primary">Confirmar orden</Button> 
         </form>
         </Container>
        </div>
    );
}

如您所见,使用 setCurrentStep (3); 我转到 Stepper 的最后一步,这将是最后一个组件,我消失了上一步中的 Element 组件和 CheckoutForm2,这就是我收到错误的地方,因为 await stripe.createPaymentMethod ({...它说我正在尝试更新不再存在的组件中的状态,但是当 setCurrentStep (3) 发生时;我不再更新任何其他内容,我不明白为什么会收到错误,所以我认为错误指等待并要求我也清理异步等待任务,但我不知道该怎么做,我必须通过相同的句柄提交清理所有内容,而不使用 useEffect,因为对于我的情况不适用。

最后我会留下一张照片

在此处输入图像描述

标签: reactjsreact-hooks

解决方案


推荐阅读