Реализация невидимой reCAPTCHA с помощью Redux Form

Я пытаюсь реализовать Invisible reCAPTCHA с помощью React и Redux Form. В общем, рабочий процесс Invisible reCAPTCHA:

  1. Визуализируйте «невидимую» CAPTCHA, вернув ее ID виджета.
  2. Вызов grecaptcha.execute с идентификатором виджета. При необходимости пользователю будет предложено решить задачу. Результат передается в функцию обратного вызова, указанную при визуализации CAPTCHA.
  3. Отправьте форму вместе с результатом CAPTCHA.

Я создал компонент React, предназначенный для использования с Field Redux Form, который отображает CAPTCHA и обновляет состояние формы после вызова grecaptcha.execute:

class ReCaptcha extends React.Component {
  render() {
    return <div ref={div => this.container=div} />
  }

  componentDidMount() {
    const { input: { onChange }, sitekey } = this.props
    grecaptcha.render(this.container, {
      sitekey,
      size: "invisible",
      callback: onChange
    })
  }
}

Однако я не знаю, как и где вызвать grecaptcha.execute вместе с идентификатором виджета при отправке формы пользователем. Я не могу вызвать его в onSubmit, потому что ID виджета там недоступен. Я мог бы вызвать это в ReCaptcha сразу после рендеринга CAPTCHA, но если пользователю нужно решить CAPTCHA, ему будет предложено сделать это, как только форма будет отрисована.

Этот минимальный рабочий пример показывает, чего я достиг на данный момент.


person csm    schedule 10.02.2017    source источник


Ответы (3)


Используйте свойство onSubmit для вызова grecaptcha.execute () и укажите обратный вызов данных на «настоящую» функцию onSubmit.

let refToMyWidget;
const { handleSubmit } = this.props;

componentDidMount() {
  if (window.grecaptcha) {
    refToMyWidget = window.grecaptcha.render(this.container, {
      sitekey: "xxxx",
      size: "invisible",
      callback: handleSubmit(this.actuallySubmit)
    })
  }
}

preSubmit() {
  if(!window.grecaptcha) {
    return;
  }
  window.grecaptcha.execute(this.refToMyWidget)
}

actuallySubmit() {
  // submission logic here
}

render() {
  return (
    <form onSubmit={handleSubmit(this.preSubmit)}>
        <Field name="foo" component="input" />
        <button>Submit</button>
    </form>
  )
}

N.b. Я не тестировал этот код, но он должен быть более или менее правильным. Если у вас возникнут проблемы с загрузкой grecaptcha на страницу / форму, я обнаружил этот код очень полезен.

person TwinkleFairyGlitterPuff    schedule 21.09.2017

Мне пришлось заставить работать невидимую reCAPTCHA, потому что видимая не реагирует. Вот реализованный мной пример.

Первое, что нужно сделать, это добавить тег ниже к телу (или вы можете использовать реагировать-шлем) .

<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>

Упрощенная версия моего рабочего кода:

import React from 'react';

class YourComponent extends React.Component {
  componentDidMount() {
    // Create a script to make sure the reCAPTCHA API is called.
    const script = document.createElement('script');
    script.text = `
      var onloadCallback = function() {
        console.log('grecaptcha is ready');
      };
    `;
    document.body.appendChild(script);

    // We will render reCAPTCHA after the page is loaded,
    // because we want to bind our own submit methods.
    window.addEventListener('load', this.onLoad);
  }

  // Runs once the form is submitted.
  onRecaptcha = (e) => {
    e.preventDefault();
    const { grecaptcha } = window;
    grecaptcha.execute();
  };

  // Real submit function.
  onSubmit = (token) => {
    // I'm not sure what token could be if recaptcha fails.
    // In my case it seems successful and returns a long string.
    console.log(token);

    // Your real action goes below...
  };

  onLoad = () => {
    // Now we define our reCAPTCHA
    if (window.grecaptcha) {
      const { grecaptcha } = window;
      grecaptcha.render('recaptcha', { // div#recaptcha
        sitekey  : '',
        size     : 'invisible',
        callback : this.onSubmit
      });
    }
  };

  render() {
    return (
      <div>
        <Helmet>
          <script
            src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
            async
            defer
          />
        </Helmet>
        <form onSubmit={this.onRecaptcha}>
          <div id="recaptcha" />
          <button type="submit">Submit</button>
        </form>
      </div>
    );
  }
}

export default YourComponent;
person Mehmet N. Yarar    schedule 03.02.2018
comment
Я понял, что это намного проще с библиотекой scriptjs. Приведу пример, если хотите. - person Mehmet N. Yarar; 08.02.2018

Таким образом, вы можете реализовать его где угодно в React

import React, { Component } from "react";

    export default class Test extends Component {

      componentWillMount = () => {
        const script = document.createElement("script");
        script.src = "https://www.google.com/recaptcha/api.js";
        script.async = true;
        script.defer = true;
        document.body.appendChild(script);

        window.addEventListener("load", this.onLoad);
      };

      onLoad = () => {
        if (window.grecaptcha) {
          window.grecaptcha.render("recaptcha", {
            sitekey: "",
            size: "invisible",
            callback: this.onCaptcheCompleted
          });
        }
      };
      onCaptcheCompleted = e => {
        //do what ever you want
        console.log(e);
      };

      render() {
        return (
          <div id="recaptcha">
            <input />
            <button onClick={() => window.grecaptcha.execute()} />
          </div>
        );
      }
    }
person saiful619945    schedule 11.04.2018