javascript - 如何使用 handleSubmit 内的 Formik promise 来更改 react 状态以显示/隐藏 div?

标签 javascript reactjs forms formik lottie

我需要你的帮助。 当使用 Formik 内的 Promise 提交表单时,我试图使用 React 的状态使 div 显示/隐藏在表单的发送按钮内。我知道它与绑定(bind)“this”有关,但我不知道在哪里绑定(bind)它。我想这样做,以便在提交成功时显示一个垃圾复选标记。

我尝试过设置:

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(高阶组件),所以您无法访问组件状态,因此您需要另一种方法。

您可以使用 setStatus,它通过 this.props.form.status 传递给您的组件。

因此,当您想要显示按钮时,您可以使用一些标志或值调用 setStatus ,并在组件中执行一个条件,以便显示/隐藏它。

您可以在this issue中看到这个问题哪里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}
/> 
}

关于javascript - 如何使用 handleSubmit 内的 Formik promise 来更改 react 状态以显示/隐藏 div?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59395105/

相关文章:

php - PHP Codeigniter 中的自定义验证 - 需要的两个字段之一

php - "add employee"没有页面重定向的表单

javascript - &lt;input type ="hidden">和全局JS变量有什么区别

javascript - 在observe()之后设置状态

reactjs - Google 跟踪代码管理器导致 SPA 中的整个页面重新加载 - React

reactjs - 使用带有 react 的 Material-UI 选项卡

javascript - 计算数据库中的行数

javascript - MongoDB 数组从 10 中匹配 6

javascript - spy 功能不起作用 - Jasmine

javascript - 为什么不从 onSubmit 发送 Google Analytics 事件?