使用useLocalStorage Hook与Context Provider时出现Too many re-renders报错
问题原因
你在useLocalStorage的顶层作用域直接执行了setItem(parsedItem),自定义Hook的所有代码会在引用它的组件每次渲染时完整执行一次:
- 组件首次渲染,执行Hook代码,调用
setItem触发重渲染 - 重渲染时再次执行Hook代码,又调用
setItem触发下一次重渲染 - 循环往复触发无限重渲染,因此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
相关产品推荐
相关产品推荐

