如何使用 Redux 表单实现 Google reCAPTCHA

How To Implement Google reCAPTCHA With Redux Form

我有一个联系页面,上面有一个定义如下的联系表单:

import React from "react";
import { Field, reduxForm } from "redux-form";
import Recaptcha from "react-recaptcha";

const required = value => (value ? undefined : "This field is required.");
const email = value => value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value) ? "Invalid email address." : undefined;

const renderInput = ({
    input,
    label,
    type,
    meta: { touched, error }
}) => (
    <div className="form-group">
        <label className="col-sm-2 control-label">{ label }</label>
        <div className="col-sm-10">
            { (type == "text" || type == "email") ? <input { ...input } type={ type } /> : <textarea { ...input }></textarea> }
            { touched && ((error && <span className="contact-form-error-message">{ error }</span>)) }
        </div>
    </div>
);

const captcha = (props) => (
    <div className="form-group">
        <label className="col-sm-2 control-label"></label>
        <div className="col-sm-10">
            <Recaptcha render="explicit" onloadCallback={ console.log.bind(this, "reCAPTCHA loaded.") }
                sitekey="XXXXXXXXXXXXXXXXX" onChange={props.input.onChange} />
        </div>
    </div>
);

const ContactForm = props => {
    const { handleSubmit, submitting } = props
    return (
        <form className="form-horizontal" onSubmit={ handleSubmit }>
            <Field
                name="name"
                type="text"
                component={ renderInput }
                label="Name:"
                validate={ required }
            />
            <Field
                name="email"
                type="email"
                component={ renderInput }
                label="Email:"
                validate={ [required, email] }
            />
            <Field
                name="subject"
                type="text"
                component={ renderInput }
                label="Subject:"
                validate={ required }
            />
            <Field
                name="message"
                type="textarea"
                component={ renderInput }
                label="Message:"
                validate={ required }
            />
            <Field name="recaptchacode" component={ captcha } />
            <div className="form-group">
              <label className="col-sm-2 control-label"></label>
              <div className="col-sm-10">
                  <button type="submit" id="contact-form-button" disabled={ submitting }>Send</button>
              </div>
            </div>
        </form>
    )
}

export default reduxForm({
    form: "ContactForm"
})(ContactForm);

问题是当我点击提交按钮时,我似乎无法获得 values 对象中的 recaptchacode 字段。如何将 Recaptcha 组件的值绑定到 redux-form 以便将其放入 values 对象中?

因为代码太多,Whosebug 希望我对此添加更多解释,所以我正在写这篇文章。

所以简而言之,我已经设法让这个东西工作了。 react中实现recaptcha的npm包有两个:

react-recaptchareact-google-recaptcha。您想要第二个而不是第一个(这是我的问题,不适用于 redux-form),然后您想按照本教程进行操作:https://github.com/erikras/redux-form/issues/1880

希望这对某人有所帮助。

以下是我如何将 Google ReCaptcha 与 React 和具有语言支持的 redux-forms 集成。希望这会对某人有所帮助。

Versions:
React: 16.5.2
react-google-recaptcha: 1.0.5
react-redux: 5.0.6
redux: 3.7.2
redux-form: 7.2.0

Redux 形式:

import React from 'react';
import {
    reduxForm,
    Field,
    formValueSelector,
    change,
} from 'redux-form';
import { testAction } from ‘/actions';
import { connect } from 'react-redux';
import Captcha from './Captcha';

const validate = values => {
    const errors = {};

    if (!values.captchaResponse) {
        errors.captchaResponse = 'Please validate the captcha.';
    }

    return errors;
};

let TestForm = (props) => {
    const {
        handleSubmit,
        testAction,
        language, //extract language from props/or hard code it in Captcha component 
    } = props;

    return (
        <Form onSubmit={ handleSubmit(testAction)}>
        <Field component={Input} name=“other_input_name” type="text" required/>
                <Field dispatch={props.dispatch} component={Captcha} change={change} language={language} name="captchaResponse"/> {/* Pass redux-forms change and language to the Captcha component*/}
                 <Button type="submit">{‘Validate’}</Button>
        </Form>
    );
};

const selector = formValueSelector('testForm');

TestForm = connect(
    state => ({
        recaptchaValue: selector(state, 'captchaResponse'),
    }),
    { testAction: testAction }
)(TestForm);

export default reduxForm({
    form: ‘testForm’,
    validate,
    enableReinitialize: true,
})(TestForm);

验证码组件:

import React, { Component } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';
import styled from 'styled-components';
import { change } from 'redux-form';

class Captcha extends Component {
    constructor(props) {
        super(props);
        window.recaptchaOptions = { lang: this.props.language }; //set language that comes from props E.g.: fr/es/en etc..
    }

    onChange = (value) => {
        this.props.meta.dispatch(change(‘testForm’, 'captchaResponse', value));
    };

    render() {
        const { meta: { touched, error } } = this.props;

        return (
            <CaptchaWrapper>
                <ReCAPTCHA
                    sitekey={‘xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’}
                    onChange={response => this.onChange(response)}
                />
                <ErrorMessage>{ touched ? error : '' }</ErrorMessage>
            </CaptchaWrapper>
        );
    }
}

const CaptchaWrapper = styled.div`
`;

const ErrorMessage = styled.p`
    color: red;
`;

export default Captcha;