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

使用useLocalStorage Hook与Context Provider时出现Too many re-renders报错

问题原因

你在useLocalStorage的顶层作用域直接执行了setItem(parsedItem),自定义Hook的所有代码会在引用它的组件每次渲染时完整执行一次:

  1. 组件首次渲染,执行Hook代码,调用setItem触发重渲染
  2. 重渲染时再次执行Hook代码,又调用setItem触发下一次重渲染
  3. 循环往复触发无限重渲染,因此React抛出超限错误
修复方案

最优解是使用useState的惰性初始化能力,把localStorage读取逻辑放到useState的初始值函数中,该函数只会在Hook第一次挂载时执行一次,不会重复触发更新:

function useLocalStorage(itemName, initialValue) {
  const [item, setItem] = React.useState(() => {
    const localStorageItem = localStorage.getItem(itemName);
    if (!localStorageItem) {
      const stringifiedInitial = JSON.stringify(initialValue);
      localStorage.setItem(itemName, stringifiedInitial);
      return initialValue;
    }
    return JSON.parse(localStorageItem);
  });
  
  const saveItem = (newItem) => {
      const stringifiedItem = JSON.stringify(newItem);
      localStorage.setItem(itemName, stringifiedItem);
      setItem(newItem);
  };

  return {
    item,
    saveItem,
  };
}

export { useLocalStorage };

如果有监听itemName动态变化的需求,可以换用useEffect方案:

function useLocalStorage(itemName, initialValue) {
  const [item, setItem] = React.useState(initialValue);

  React.useEffect(() => {
    const localStorageItem = localStorage.getItem(itemName);
    let parsedItem;
    if (!localStorageItem) {
      localStorage.setItem(itemName, JSON.stringify(initialValue));
      parsedItem = initialValue;
    } else {
      parsedItem = JSON.parse(localStorageItem);
    }
    setItem(parsedItem);
  }, [itemName, initialValue]);
  
  const saveItem = (newItem) => {
      const stringifiedItem = JSON.stringify(newItem);
      localStorage.setItem(itemName, stringifiedItem);
      setItem(newItem);
  };

  return {
    item,
    saveItem,
  };
}

export { useLocalStorage };

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 17:39:03