I'm trying to use react-recaptcha with antd, the following is my source code:
import React from 'react';
import 'antd/dist/antd.css';
import Form from 'antd/lib/form';
import Input from 'antd/lib/input';
import Tooltip from 'antd/lib/tooltip';
import Icon from 'antd/lib/icon';
import Cascader from 'antd/lib/cascader';
import Row from 'antd/lib/row';
import Col from 'antd/lib/col';
import Checkbox from 'antd/lib/checkbox';
import Button from 'antd/lib/button';
import Recaptcha from 'react-recaptcha';
const FormItem = Form.Item;
const residences = [{
value: 'zhejiang',
label: 'Zhejiang',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
children: [{
value: 'xihu',
label: 'West Lake',
}],
}],
}, {
value: 'jiangsu',
label: 'Jiangsu',
children: [{
value: 'nanjing',
label: 'Nanjing',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
}];
class RegisterForm extends React.Component {
constructor(props) {
super(props);
this.state = {
passwordDirty: false,
};
}
handleSubmit(e) {
e.preventDefault();
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
}
handlePasswordBlur(e) {
const value = e.target.value;
this.setState({ passwordDirty: this.state.passwordDirty || !!value });
}
checkPassowrd(rule, value, callback) {
const form = this.props.form;
if (value && value !== form.getFieldValue('password')) {
callback('Two passwords that you enter is inconsistent!');
} else {
callback();
}
}
checkConfirm(rule, value, callback) {
const form = this.props.form;
if (value && this.state.passwordDirty) {
form.validateFields(['confirm'], { force: true });
}
callback();
}
myCallback(e) {
console.log(e);
}
loaded() {
console.log("loaded");
}
render() {
const { getFieldDecorator } = this.props.form;
const formItemLayout = {
labelCol: { span: 6 },
wrapperCol: { span: 14 },
};
const tailFormItemLayout = {
wrapperCol: {
span: 14,
offset: 6,
},
};
return (
<Form horizontal onSubmit={this.handleSubmit.bind(this)}>
<FormItem
{...formItemLayout}
label={(
<span>
Username
<Tooltip title="What do you want other to call you?">
<Icon type="question-circle-o" />
</Tooltip>
</span>
)}
hasFeedback
>
{getFieldDecorator('username', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="Password"
hasFeedback
>
{getFieldDecorator('password', {
rules: [{
required: true, message: 'Please input your password!',
}, {
validator: this.checkConfirm.bind(this),
}],
})(
<Input type="password" onBlur={this.handlePasswordBlur.bind(this)} />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="Confirm Password"
hasFeedback
>
{getFieldDecorator('confirm', {
rules: [{
required: true, message: 'Please confirm your password!',
}, {
validator: this.checkPassowrd.bind(this),
}],
})(
<Input type="password" />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="E-mail"
hasFeedback
>
{getFieldDecorator('email', {
rules: [{
type: 'email', message: 'The input is not valid E-mail!',
}, {
required: true, message: 'Please input your E-mail!',
}],
})(
<Input />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="Habitual Residence"
>
{getFieldDecorator('residence', {
initialValue: ['zhejiang', 'hangzhou', 'xihu'],
rules: [{ type: 'array', required: true, message: 'Please select your habitual residence!' }],
})(
<Cascader options={residences} />
)}
</FormItem>
<FormItem {...tailFormItemLayout} style={{ marginBottom: 8 }}>
{getFieldDecorator('agreement', {
valuePropName: 'checked',
rules: [{ required: true, message: 'Please check the agreement!' }],
})(
<Checkbox>I had read the <a>agreement</a></Checkbox>
)}
</FormItem>
<Recaptcha
sitekey='mykeyxxxxxxxxxxxxxxxxmykey'
onloadCallback={this.loaded.bind(this)}
verifyCallback={this.myCallback.bind(this)}
/>
<FormItem {...tailFormItemLayout}>
<Button type="primary" htmlType="submit" size="large">Register</Button>
</FormItem>
</Form>
);
}
}
export default Form.create()(RegisterForm);
But in the web page, the reCAPTCHA can not even show up. I think the Form
component is a little magic and I probably did some thing not correct.
Especially two things may need attention:
const RecaptchaItem = React.createClass({..})
globally, do not make it a local variable in render()
onloadCallback
and verifyCallback
both, if onloadCallback
is missing, the reCAPTCHA will not trigger calling verifyCallback
and the Form can not get the value. This is probably a bug of react-recaptchaHere is the correct code:
const { Form, Icon, Input, Button, Checkbox } = antd;
const FormItem = Form.Item;
const RecaptchaItem = React.createClass({
verifyCallback(result) {
console.log('verifyCallback', result);
this.props.onChange(result); // notify the form after verified
},
render() {
return (<ReactRecaptcha
render="explicit"
sitekey="6LdSLAwUAAAAAFBwEUIlvzTxJE8zpRlh9r87eCL5"
onloadCallback={() => {}}
verifyCallback={this.verifyCallback}
/>);
}
});
const NormalLoginForm = Form.create()(React.createClass({
handleSubmit(e) {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
},
render() {
const { getFieldDecorator } = this.props.form;
return (
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem>
{getFieldDecorator('userName', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input addonBefore={<Icon type="user" />} placeholder="Username" />
)}
</FormItem>
<FormItem>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input addonBefore={<Icon type="lock" />} type="password" placeholder="Password" />
)}
</FormItem>
<FormItem>
{getFieldDecorator('captcha', {
rules: [{ required: true, message: 'Please input the captcha you got!' }],
})(<RecaptchaItem />)}
</FormItem>
<FormItem>
{getFieldDecorator('remember', {
valuePropName: 'checked',
initialValue: true,
})(
<Checkbox>Remember me</Checkbox>
)}
<a className="login-form-forgot">Forgot password</a>
<Button type="primary" htmlType="submit" className="login-form-button">
Log in
</Button>
Or <a>register now!</a>
</FormItem>
</Form>
);
},
}));
ReactDOM.render(<NormalLoginForm />,document.getElementById('container'));
See the live demo here
The most valuable information is already in this answer, in case someone who is interested, however, here is the original discussion link on Github issue: https://github.com/ant-design/ant-design/issues/3878
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With