Next.js中从localStorage取数时如何避免无限循环?
解决Next.js中useEffect读取localStorage的无限循环与数据不更新问题
问题根源
- 空依赖数组
[]:useEffect仅在组件挂载时执行一次,新增数据后不会主动重新读取localStorage,必须刷新页面才能获取新数据。 - 依赖
[data]:每次data状态更新都会触发useEffect,而useEffect里的setData又会再次修改data,形成无限循环。
正确解决方案
方案1:提交时同步更新状态与localStorage
直接在提交函数里同时更新状态和localStorage,无需依赖useEffect重复读取,这是最简洁的方式:
const LocalStorage = () => { const [data, setData] = useState([]); const [id, setId] = useState(""); const [name, setName] = useState(""); const [city, setCity] = useState(""); // 组件挂载时读取初始数据 useEffect(() => { const fetchedData = localStorage.getItem("user"); if (fetchedData) { setData(JSON.parse(fetchedData)); } }, []); const handleSubmit = () => { // 构造新数据 const newUser = { id, name, city }; const updatedData = [...data, newUser]; // 同步更新localStorage和状态 localStorage.setItem("user", JSON.stringify(updatedData)); setData(updatedData); // 清空表单 setId(""); setName(""); setCity(""); }; // 省略渲染逻辑... };
方案2:监听localStorage变化(跨页面场景)
如果需要监听其他页面修改localStorage的情况,可以添加storage事件监听,注意该事件仅在同源的其他标签页/窗口触发:
useEffect(() => { // 读取初始数据 const initData = localStorage.getItem("user"); if (initData) setData(JSON.parse(initData)); // 监听storage变化 const handleStorageChange = (e) => { if (e.key === "user") { setData(JSON.parse(e.newValue)); } }; window.addEventListener("storage", handleStorageChange); return () => window.removeEventListener("storage", handleStorageChange); }, []);
关键注意点
- 避免在依赖包含
data的useEffect里调用setData,这必然导致无限循环。 - 操作localStorage时记得判断
getItem的返回值,避免JSON.parse(null)报错。 - 表单状态初始化建议设为空字符串
"",而非undefined,避免渲染时出现异常。
内容的提问来源于stack exchange,提问作者Rohit Sahani
相关产品推荐
相关产品推荐

