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

如何避免子组件状态变化时重新初始化Formik单个字段

解决方案

方法1:监听Recoil状态,单独更新Formik字段

保留enableReinitialize用于提交后的表单重置,同时通过监听Recoil状态变化,调用Formik的setFieldValue单独更新目标字段,避免重置整个表单。

修改后的父组件代码:

const MembersCreate = memo(() => {
  const urlGDPR = useRecoilValue(urlGDPRState);
  // 初始化时gdpr_form_link设为空,后续通过setFieldValue更新
  const initialValues = {
    forename: '',
    surname: '',
    gdpr_form_link: '',
    // 其他字段
  };
  // 获取Formik上下文实例
  const { setFieldValue } = useFormikContext();

  // 监听urlGDPR变化,仅更新指定字段
  useEffect(() => {
    if (urlGDPR) {
      setFieldValue('gdpr_form_link', urlGDPR);
    }
  }, [urlGDPR, setFieldValue]);

  return (
    <Formik
      enableReinitialize={true}
      initialValues={initialValues}
      onSubmit={(values, formik) => {
        mutate(values, {
          onSuccess: () => formik.resetForm()
        });
      }}
    >
      <Form>
        <UploadWidget />
        <CustomTextField name="gdpr_form_link" readOnly={true}/>
      </Form>
    </Formik>
  );
});

优势:

  • enableReinitialize依然生效,提交成功后formik.resetForm()可以正确重置所有字段到初始值
  • 当urlGDPRState更新时,仅修改gdpr_form_link字段,完全不影响用户已填写的其他内容

补充:修复子组件内存泄漏问题

子组件中需要在卸载时销毁Cloudinary widget实例,避免内存泄漏:

const UploadWidget = () => {
  const [, setUrlGDPR] = useRecoilState(urlGDPRState);
  useEffect(() => {
    const widget = window.cloudinary.createUploadWidget(
      { cloudName: '*removed*', uploadPreset: '*removed*' },
      (error, result) => {
        if (result?.event === 'success') setUrlGDPR(result.info.secure_url);
      }
    );

    // 组件卸载时销毁widget
    return () => widget.destroy();
  }, []);

  // 添加触发上传的按钮(原代码缺失此部分)
  return <button onClick={() => widget.open()}>上传GDPR表单</button>;
};

内容的提问来源于stack exchange,提问作者Jess

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:50:30