Redux+Formik架构下表单提交后重置react-google-recaptcha
解决表单提交后重置react-google-recaptcha的问题
核心思路是通过React转发Ref将自定义ReCaptcha组件内部的重置方法暴露给父组件,然后在表单提交完成时触发重置操作。
步骤1:修改自定义ReCaptcha组件,暴露重置方法
使用React.forwardRef和useImperativeHandle将内部的recaptcha实例重置方法暴露给上层组件:
import React, { forwardRef, useImperativeHandle, useRef } from "react"; import ReCAPTCHA from "react-google-recaptcha"; interface OwnProps { onChange(value: any): any; } // 定义暴露给父组件的方法类型 interface ReCaptchaHandle { reset: () => void; } const ReCaptcha = forwardRef<ReCaptchaHandle, OwnProps>((props, ref) => { const { onChange } = props; const recaptchaRef = useRef<ReCAPTCHA>(null); const siteKey = String(process.env.REACT_APP_GOOGLE_SITE_KEY); // 向父组件暴露reset方法 useImperativeHandle(ref, () => ({ reset: () => { recaptchaRef.current?.reset(); }, })); return ( <ReCAPTCHA ref={recaptchaRef} sitekey={siteKey} size="normal" onChange={onChange} theme="dark" /> ); }); ReCaptcha.displayName = "ReCaptcha"; export default ReCaptcha;
步骤2:修改LoginForm组件,监听提交状态并触发重置
在LoginForm中创建Ref关联ReCaptcha组件,通过监听Formik的isSubmitting状态变化,在表单提交完成后执行重置:
import { Field, Form, InjectedFormikProps } from "formik"; import * as React from "react"; import ReCaptcha from './ReCaptcha'; // 根据实际路径调整 export const LoginForm: React.FunctionComponent< InjectedFormikProps<{}, LoginFormValues> > = (props) => { const { isSubmitting, setFieldValue } = props; // 创建Ref关联ReCaptcha组件 const recaptchaRef = React.useRef<{ reset: () => void }>(null); function onChangeCAPTCHA(value: any) { setFieldValue("captchaToken", value); } // 当表单提交完成(isSubmitting从true切换为false)时执行重置 React.useEffect(() => { if (!isSubmitting) { recaptchaRef.current?.reset(); // 同时清空表单中的captchaToken字段 setFieldValue("captchaToken", null); } }, [isSubmitting, setFieldValue]); return ( <Form> <FormFieldsWrapper> <Field type="email" label="Email" name="email" component={TextInput} /> </FormFieldsWrapper> <FormFieldsWrapper> <Field type="password" label="Password" name="password" component={TextInput} /> </FormFieldsWrapper> <FormFieldsWrapper> {/* 将Ref传递给ReCaptcha组件 */} <ReCaptcha ref={recaptchaRef} onChange={onChangeCAPTCHA} /> </FormFieldsWrapper> <FormFieldsWrapper> <Button fullWidth={true} primary={true} disabled={isSubmitting} loading={isSubmitting} type="submit" style={{ marginTop: 20 }} > Login </Button> </FormFieldsWrapper> </Form> ); }; export default LoginForm;
说明
- 无需修改LoginFormContainer组件,逻辑内聚在LoginForm中,通过监听Formik的提交状态自动触发重置。
useEffect会在isSubmitting变为false时执行,对应表单提交完成(无论成功或失败),确保用户下次提交必须重新验证captcha。- 同时清空
captchaToken字段,保证表单验证逻辑的一致性。
内容的提问来源于stack exchange,提问作者Cya
相关产品推荐
相关产品推荐

