You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 10:01:43