【问题标题】:How to make invisible react-google-recaptcha, Formik and yup work together?如何让无形的 react-google-recaptcha、Formik 和 yup 协同工作?
【发布时间】:2021-01-26 12:56:00
【问题描述】:

我试图让react-google-recaptchaFormikyup 一起工作。文档说我们应该在提交表单时调用recaptchaRef.current.execute(),但是如果我们同时使用Formik和yup,它只会在所有字段都通过验证模式后触发提交逻辑。

基本上,我们需要调用execute 方法,更新recaptcha 值并使用相同的触发事件提交表单。我的问题正是:我必须使用两个事件(一个用于execute 方法并更新recaptcha + 一个用于提交表单)。

检查此沙盒:https://codesandbox.io/s/keen-mahavira-ont8z?file=/src/App.js

如您所见,表单仅在第二次点击提交按钮时提交...

【问题讨论】:

    标签: reactjs formik yup invisible-recaptcha react-google-recaptcha


    【解决方案1】:

    使用 Formik,有一些方法可以为您的表单做后台工作。这基本上可以通过将handleChangehandleBlur 道具传递给表单组件来实现。

    例如,我相信您的表单元素中会有其他输入,而不仅仅是验证码 (if it's just a captcha in the form, then do let me know! - this can also be solved)

    所以当你有其他元素时,你可以确保使用Formik的一些API来处理自动触发:

    正如我所见,有很多方法可以通过他们的 API 处理这个问题:https://formik.org/docs/api/formik

    我尝试实现它的方法是在所有字段上添加onBlur 的侦听器,然后检查是否存在 reCaptcha 值。基于此,我触发执行验证码并确保将提交值设置为 true:

    const handleBlur = (e) => {
      console.log("$$$$", props.isSubmitting);
      if (!props.values.recaptcha) {
        this._reCaptchaRef.current.execute();
        props.setSubmitting(true);
      }
      props.handleBlur(e);
    };
    

    这里是 CodeSandbox 链接:https://codesandbox.io/s/silly-saha-qq7hg?file=/src/App.js

    这显示了处理一个字段的onBlur 并在后台触发它的工作模型。如果您注意到,您还可以使用isSubmittingsetSubmitting 禁用和启用提交按钮。

    同时设置validateOnChange={false}validateOnBlur={false},因为不需要验证验证码的更改或模糊。

    在此处粘贴代码以供您浏览:

    import React, { Component, createRef } from "react";
    
    import ReCAPTCHA from "react-google-recaptcha";
    import { Formik } from "formik";
    import * as yup from "yup";
    
    const TEST_SITE_KEY = "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI";
    
    export default class MyForm extends Component {
      constructor(props) {
        super(props);
        this._validationSchema = yup.object().shape({
          recaptcha: yup.string().required(),
          name: yup.string().required(),
          address: yup.string().required()
        });
        this._initialValues = { recaptcha: "", name: "", address: "" };
        this._reCaptchaRef = createRef();
      }
    
      render() {
        return (
          <Formik
            validationSchema={this._validationSchema}
            initialValues={this._initialValues}
            validateOnChange={false}
            validateOnBlur={false}
            onSubmit={(values) => console.log(values)}
          >
            {(props) => {
              const handleBlur = (e) => {
                console.log("$$$$", props.isSubmitting);
                if (!props.values.recaptcha) {
                  this._reCaptchaRef.current.execute();
                  props.setSubmitting(true);
                }
                props.handleBlur(e);
              };
    
              return (
                <form onSubmit={props.handleSubmit}>
                  <label>Name: </label>
                  <input
                    type="text"
                    onChange={props.handleChange}
                    value={props.values.name}
                    name="name"
                    onBlur={handleBlur}
                  />
                  <label>Address: </label>
                  <input
                    type="text"
                    onChange={props.handleChange}
                    value={props.values.address}
                    name="address"
                    onBlur={handleBlur}
                  />
                  <ReCAPTCHA
                    ref={this._reCaptchaRef}
                    sitekey={TEST_SITE_KEY}
                    onChange={(value) => {
                      console.log("$$$$", props.isSubmitting, value);
                      props.setFieldValue("recaptcha", value);
                      props.setSubmitting(false);
                    }}
                    size="invisible"
                  />
                  <button type="submit" disabled={props.isSubmitting}>
                    SUBMIT
                  </button>
    
                  {props.errors.name && <div>{props.errors.name}</div>}
                </form>
              );
            }}
          </Formik>
        );
      }
    }
    

    【讨论】:

    • 这个答案似乎是我现在需要的一切,但它根本不适合我。我正在使用功能组件和 withFormik,但基本相同 - 我有 handleBlur 事件,它使用由 useRef() 钩子创建的 ref 并调用 _reCaptchaRef.current.execute(),但没有任何反应。请求未发送(我在开发工具中查看网络选项卡)并且 ReCAPTCHA onChange 永远不会触发。我不知道发生了什么。
    • @OdifYltsaeb 如果可能,请随时分享代码和框。将检查并提供我在那里找到的任何信息。
    • 功能组件似乎有问题。我重新创建了与基于类的组件相同的组件,并且效果很好:codesandbox.io/s/nifty-architecture-r0gzj?file=/src/App.js(如果您使用测试密钥而不是它当前拥有的密钥)
    • @OdifYltsaeb 在您的 functional component 代码和框中将您的 import { ReCAPTCHA } from "react-google-recaptcha"; 更改为 import ReCAPTCHA from "react-google-recaptcha"; 并且它正在工作
    猜你喜欢
    • 2020-10-14
    • 2021-12-29
    • 1970-01-01
    • 2020-01-01
    • 2020-12-12
    • 1970-01-01
    • 2020-01-17
    • 2017-11-15
    • 2020-01-13
    相关资源
    最近更新 更多