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

React项目中Formik因初始值变更引发无限渲染的问题求助

解决Formik结合localStorage导致的无限渲染问题

你遇到的这个无限渲染问题,根源其实出在prefilledValues的获取方式和useEffect的依赖设置上,咱们一步步拆解并解决它:

问题核心分析

你现在的代码里,prefilledValues是在组件每次渲染时直接从localStorage读取并解析的——这意味着每次组件渲染,它都会生成一个全新的对象引用。而你的useEffect依赖数组里包含了prefilledValues,同时useEffect内部又会更新localStorage,这就形成了一个死循环:

  1. 组件渲染,读取localStorage得到新的prefilledValues对象
  2. useEffect检测到prefilledValues引用变化,执行更新localStorage的操作
  3. localStorage更新后,组件因formik.values变化重新渲染,再次读取localStorage生成新的prefilledValues
  4. 循环回到步骤2,最终导致组件无限渲染、页面无响应

最简单的修复方案

我们只需要把初始值的获取逻辑放到useState里,让它只在组件第一次挂载时读取一次localStorage,这样initialValues的引用就不会每次渲染都变化:

// 用useState初始化,仅在组件挂载时读取一次localStorage
const [initialValues] = useState(() => {
  const savedData = window.localStorage.getItem("pre-signup-form");
  // 这里填你的表单默认初始值,比如name为空字符串
  return savedData ? JSON.parse(savedData) : { name: "" };
});

// 初始化Formik时使用这个固定的initialValues
const formik = useFormik({
  initialValues: initialValues,
  // 你的其他Formik配置(比如validationSchema、onSubmit等)
});

// 修改useEffect的依赖,只监听formik.values的变化
useEffect(() => {
  window.localStorage.setItem(
    "pre-signup-form",
    JSON.stringify(formik.values)
  );
}, [formik.values]);

这样调整后:

  • initialValues只会在组件第一次加载时从localStorage读取,后续不会再重新生成新对象
  • useEffect只在formik的表单值变化时更新localStorage,不会因为引用变化被误触发
  • 彻底打破了之前的循环逻辑

进阶:支持外部修改localStorage同步(可选)

如果你希望其他页面或浏览器标签页修改了pre-signup-form的localStorage数据时,当前组件的表单能同步更新,可以添加storage事件监听,但要注意避免自身更新导致的循环:

const [initialValues] = useState(() => {
  const savedData = window.localStorage.getItem("pre-signup-form");
  return savedData ? JSON.parse(savedData) : { name: "" };
});

const formik = useFormik({
  initialValues: initialValues,
  onSubmit: (values) => {
    // 你的表单提交逻辑
  },
});

// 监听外部的storage变化(比如其他标签页修改了localStorage)
useEffect(() => {
  const handleExternalStorageChange = (e) => {
    if (e.key === "pre-signup-form") {
      const updatedValues = JSON.parse(e.newValue);
      // 用Formik的setValues方法更新表单值,避免直接修改state引发的问题
      formik.setValues(updatedValues);
    }
  };

  window.addEventListener("storage", handleExternalStorageChange);
  // 组件卸载时移除监听
  return () => window.removeEventListener("storage", handleExternalStorageChange);
}, [formik]);

// 同步自身表单修改到localStorage
useEffect(() => {
  window.localStorage.setItem(
    "pre-signup-form",
    JSON.stringify(formik.values)
  );
}, [formik.values]);

这个方案里,我们把自身修改localStorage和外部修改localStorage的逻辑分开,既实现了跨标签页的数据同步,又不会触发无限渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 18:34:08