如何使用 handleSubmit 中的 Formik 承诺将反应状态更改为 show/hide a div?

How do I change react state using a promise with Formik inside handleSubmit to show/hide a div?

我需要你的帮助。 当使用 Formik 中的承诺提交表单时,我正在尝试使用 React 的状态在表单的发送按钮内创建一个 div show/hide 。我知道它与绑定 'this' 有关,但我不知道在哪里绑定它。我想这样做,以便在提交成功时显示垃圾复选标记。

我试过设置:

const that = this;

然后使用 'that' 和 checkSuccesBoxShowHandler 方法。但它在控制台中抛出了这个:

TypeError: Cannot read property 'checkSuccesBoxShowHandler' of undefined

代码如下:

class CForm extends React.Component {

    state = {
        checkSuccesBoxShow: false
    }

    checkSuccesBoxShowHandler = () => {
        this.setState({
            checkSuccesBoxShow: true
        });
        setTimeout(() => {
            this.setState({
                checkSuccesBoxShow: false
            })
        }, 3000);
    }

    render() {
        const {
            errors,
            touched,
            isSubmitting,
            handleSubmit,
            isValid,
            bgColor
        } = this.props;

        const checkSuccessLottieOptions = {
            loop: false,
            autoplay: true,
            animationData: checkSuccessLottie,
            name: 'checkMarkSuccess',
            rendererSettings: {
                preserveAspectRatio: 'xMidYMid slice'
            }
        };

        return (
            <Form className={classes.contactForm} onSubmit={handleSubmit}>
                <div className={classes.inputBox}>
                    <label className={touched.name && errors.name ? [classes.label, classes.labelError].join(' ') : classes.label} >Mi nombre es
                    <ErrorMessage name='name' component='p' className={classes.error} />
                        <Field type='text' name='name' placeholder='Tu nombre' autoComplete='name' className={bgColor ? [classes.inputElement, classes[bgColor]].join(' ') : classes.inputElement} />
                    </label>
                </div>
                <div className={classes.inputBox}>
                    <label className={touched.email && errors.email ? [classes.label, classes.labelError].join(' ') : classes.label} >Contáctame a
                    <ErrorMessage name='email' component='p' className={classes.error} />
                        <Field type='email' name='email' placeholder='tu@correo.com' autoComplete='email' className={bgColor ? [classes.inputElement, classes[bgColor]].join(' ') : classes.inputElement} />
                    </label>
                </div>
                <div className={classes.inputBox}>
                    <label className={touched.phone && errors.phone ? [classes.label, classes.labelError].join(' ') : classes.label} >Mi número de teléfono es
                    <ErrorMessage name='phone' component='p' className={classes.error} />
                        <Field type='phone' name='phone' placeholder='Tu número de teléfono' autoComplete='tel' className={bgColor ? [classes.inputElement, classes[bgColor]].join(' ') : classes.inputElement} />
                    </label>
                </div>
                <div className={classes.inputBox}>
                    <label className={touched.company && errors.company ? [classes.label, classes.labelError].join(' ') : classes.label} >Trabajo en
                    <ErrorMessage name='company' component='p' className={classes.error} />
                        <Field type='text' name='company' placeholder='Tu compañía' autoComplete='organization' className={bgColor ? [classes.inputElement, classes[bgColor]].join(' ') : classes.inputElement} />
                    </label>
                </div>
                <div className={classes.inputBox}>
                    <label className={touched.message && errors.message ? [classes.label, classes.labelError].join(' ') : classes.label} >Mensaje
                    <ErrorMessage name='message' component='p' className={classes.error} />
                        <Field component='textarea' name='message' placeholder='Empieza a escribir...' autoComplete='off' className={bgColor ? [classes.textAreaElement, classes[bgColor]].join(' ') : classes.textAreaElement} />
                    </label>
                </div>
                <button type='submit'
                    className={classes.sendBtn}
                    disabled={isSubmitting || !isValid}
                >
                    <span style={isSubmitting ? { display: 'none' } : null}>Enviar</span>
                    <div className={isSubmitting ? [classes['sk-circle'], classes.showing].join(' ') : classes['sk-circle']}>
                        <div className={[classes['sk-circle1'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle2'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle3'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle4'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle5'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle6'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle7'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle8'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle9'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle10'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle11'], classes['sk-child']].join(' ')}></div>
                        <div className={[classes['sk-circle12'], classes['sk-child']].join(' ')}></div>
                    </div>
                    <div style={this.state.checkSuccesBoxShow
                        ? { display: 'inline-block' }
                        : { display: 'none' }} >
                        <Lottie
                            options={checkSuccessLottieOptions}
                            height={50}
                            width={50}
                        />
                    </div>
                </button>
            </Form>
        );
    }
};

const ContactForm = withFormik({
    mapPropsToValues({ name, email, phone, company, message }) {
        return {
            name: name || '',
            email: email || '',
            phone: phone || '',
            company: company || '',
            message: message || ''
        }
    },
    validationSchema: Yup.object().shape({
        name: Yup.string().required('El nombre es requerido'),
        email: Yup.string().email('Email invalido').required('Email requerido'),
        phone: Yup.number().typeError('Debe ser un número telefónico'),
        company: Yup.string(),
        message: Yup.string().required('Mensaje requerido')
    }),
    handleSubmit(values, { resetForm, setSubmitting }) {
        // This is the endpoint we created in our API Gateway. This is where we make our POST request, which calls our Lambda function.
        const endpoint = '***********';

        // We replace line to keep format of text in message value
        const messageText = values.message;
        const formattedMessageText = messageText.replace(/\n/g, '<br />');
        let newValues = { ...values };
        newValues.message = formattedMessageText;

        // Here, we instantiate our Request. This is a special object used by the Fetch API so it knows where to send data, what data to send, and how to send it.
        var lambdaRequest = new Request(endpoint, {
            method: 'POST',
            // Quick note: 'no-cors' mode is for development on localhost only!
            mode: 'no-cors',
            body: JSON.stringify(newValues)
        });

        const that = this;

        // Call the Fetch API to make our request
        fetch(lambdaRequest)
            .then(response => {
                console.log(response)
                resetForm();
                setSubmitting(false);
                that.checkSuccesBoxShowHandler();
            })
            .catch(err => console.log(err));

    }
})(CForm)

export default ContactForm

因为您在 withFormik 内部,这是一个 HOC(高阶组件),您无法访问组件状态,因此您需要另一种方法。

您可以使用由 this.props.form.status 传递给您的组件的 setStatus

所以当你想显示按钮时,你调用 setStatus 带有一些标志或值,在你的组件中你做一个条件,所以 show/hide 它。

你可以在this issue where this answer your problem中看到这个问题。

对于你的情况,你需要做类似

的事情
handleSubmit(values, { resetForm, setSubmitting, setStatus }) {
    // Call the Fetch API to make our request
    fetch(lambdaRequest)
        .then(response => {
            console.log(response)
            resetForm();
            setSubmitting(false);
            setStatus(true); // setStatus  to communicate with the component
            that.checkSuccesBoxShowHandler();
        })
        .catch(err => console.log(err));
}

在你的组件中

{this.props.form.status && <Lottie
    options={checkSuccessLottieOptions}
    height={50}
    width={50}
/> 
}