Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
538 views
in Technique[技术] by (71.8m points)

reactjs - How to make invisible react-google-recaptcha, Formik and yup work together?

I'm trying to make invisible react-google-recaptcha, Formik and yup to work together. The documentation says we should call recaptchaRef.current.execute() on form submission, but if we use Formik and yup together, it will trigger the submission logic only after all fields passed the validation schema.

Basically, we need to call the execute method, update the recaptcha value and submit the form with the same trigger event. My problem is exactly that: I'm having to use two events (one for the execute method and update the recaptcha + one to submit the form).

Check this sandbox: https://codesandbox.io/s/keen-mahavira-ont8z?file=/src/App.js

As you can see, the form is submitted only with the second click in the submit button...

question from:https://stackoverflow.com/questions/65901771/how-to-make-invisible-react-google-recaptcha-formik-and-yup-work-together

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

With Formik, there are some ways to do background work for your form's. This basically could be achieved with handleChange or handleBlur props being passed to the form component.

For instance, I am sure you would have other inputs in your form elements and not just a captcha (if it's just a captcha in the form, then do let me know! - this can also be solved)

So when you have other elements, you can ensure to use some of the Formik's API to handle the automatic trigger:

As I see, there are a lot of ways to handle this through their API's: https://formik.org/docs/api/formik

The way I tried to achieve it is by adding a listener for onBlur on all fields and then checking if reCaptcha value is present or not. Based on that I trigger the execute the captcha and ensure to set the submitting value as true:

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

Here is the CodeSandbox Link: https://codesandbox.io/s/silly-saha-qq7hg?file=/src/App.js

This shows the working model of handling onBlur of a field and triggering it in the background. If you notice, you can also disable and enable the submit button using isSubmitting and setSubmitting.

Also setting validateOnChange={false} and validateOnBlur={false}, because there is no need to validate on change or blur for captcha.

Pasting code here just in case for you to glance:

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>
    );
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...