如何使用Redux表单实现Google reCAPTCHA

时间:2017-10-18 21:00:34

标签: reactjs recaptcha 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);

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

由于StackOverflow希望我为此添加更多解释,因为代码太多,我正在编写此文本。

2 个答案:

答案 0 :(得分:4)

所以简而言之,因为我已经设法使这件事起作用。有两个npm包用于在react中实现recaptcha:

react-recaptchareact-google-recaptcha。你想要第二个而不是第一个(这是我的问题而且不能用于redux-form)然后你想要学习本教程:https://github.com/erikras/redux-form/issues/1880

希望这有助于某人。

答案 1 :(得分:1)

在这里,我将Google ReCaptcha与React和具有语言支持的redux-forms集成在一起。希望这会帮助某人。

  

版本:
  反应:16.5.2
  react-google-recaptcha:1.0.5
  react-redux:5.0.6
  redux:3.7.2
  redux形式: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;