Resetting captcha with redux-form
How do I reset captcha if I'm using redux-form ?
export const FormCaptcha = ({ input }) => {}
<ReCAPTCHA {...input}
sitekey="xxxxxxxxxxxxx"
/>
<Field
name="g-recaptcha-response"
component={FormCaptcha}
/>
class Captcha extends React.Component {
constructor(props) {
super(props)
this.state = {
shouldReset: false
}
this.component = React.createRef()
}
static getDerivedStateFromProps(nextProps, prevState) {
return { shouldReset: nextProps.reset }
}
render() {
return (
<ReCAPTCHA
ref="recaptcha"
sitekey={this.props.sitekey}
onChange={value => this.props.onChange(value)}
ref={this.component}
/>
)
}
componentDidUpdate() {
if (this.state.shouldReset) this.component.current.reset()
}
}
<Captcha
sitekey="XXX"
reset={this.state.shouldCaptchaReset}
onChange={value => {
this.setState({ captcha: value, shouldCaptchaReset: false })
}}
/>
I use this and it works, but I don't know if this is a good thing : every time captcha send a value to the form (which handle captcha), should Captcha reset is set to false. But when I send the form, if an error occurs (another field is missing for exemple), I set the shouldCaptchaReset to false, so the captcha is reseting and will need another ok from google, otherwise it will reset at each render
You might need to include the withRef option on the Field component, which then allows you access to the getRenderedComponent method, so you can reach the component that renders your recaptcha component. You can then use refs to call the reset method from a parent component (so long as it's class-based).
See redux form docs
e.g.
<Field
component={RenderRecaptcha}
classNames="justify-content-end"
name="recaptcha"
ref={el => {
this.captcha = el;
}}
withRef
/>
Then where you want to reset it, you can write:
const captcha = this.captcha;
captcha.getRenderedComponent().reset();
In my app I'm reaching through a couple of component levels, so I have a basic reset method on the parent of the recaptcha component using refs (as it's decorated with validation bumf to connect with redux form's various 'valid', 'invalid', 'touched' props etc.), which is rendered by the redux form Field component prop. I then trigger that reset handler through the Field using the above refs process.
another solution that works for me:
import React from 'react'
import Label from 'Shared/components/FormElements/Label/Label'
import ReCAPTCHA from 'react-google-recaptcha'
import withTranslations from 'Shared/hoc/withTranslations'
class Captcha extends React.Component {
captcha = {}
componentWillReceiveProps (nextProps) {
if (this.props.meta.submitting && !nextProps.meta.submitting && !nextProps.submitFailed) {
this.captcha.reset()
}
}
render () {
const { input: { onChange }, meta: { error }, t } = this.props
return (
<div className={`captcha-container ${error && 'captcha-container__error'}`}>
{error && <Label>{t(error.key)}</Label>}
<ReCAPTCHA
sitekey={process.env.REACT_APP_GOOGLE_RECAPTCHA_API_KEY}
onChange={onChange}
ref={el => { this.captcha = el }}
/>
</div>
)
}
}
export default withTranslations(Captcha)