React使用useEffect实现心愿单实时计数触发无限重渲染问题咨询
问题分析
你当前的代码陷入了状态更新死循环:useEffect的依赖数组包含wishlist状态,而effect回调内部又调用了setWishlist更新这个状态,每次状态更新都会重新触发effect执行,无限循环最终触发Maximum update depth exceeded警告。
当你把wishlist从依赖数组移除后,useEffect只会在组件首次挂载时执行一次,后续心愿单数据更新后没有触发状态同步,所以必须刷新页面才能拿到最新值。
最优解决方案
核心思路是状态变更和本地存储更新同步执行,不要通过监听状态反向同步存储,避免循环依赖。
具体实现步骤:
- 初始化阶段:用空依赖的useEffect只在组件首次挂载时从localStorage加载初始数据
- 封装心愿单操作方法:新增/移除商品的操作同时更新本地状态
wishlist和localStorage,状态更新后组件会自动重渲染,爱心计数就会实时同步 - (可选)如果需要支持多标签页数据同步,可以监听window的
storage事件,当其他标签页修改心愿单时同步更新当前页面状态
代码示例
const [wishlist, setWishlist] = React.useState([]); // 初始化:仅组件挂载时从localStorage读一次数据 React.useEffect(() => { if (typeof window === "undefined") return; const storageWishlist = localStorage.getItem("wishlist"); if (storageWishlist) { setWishlist(JSON.parse(storageWishlist)); } }, []); // (可选)多标签页同步监听 React.useEffect(() => { if (typeof window === "undefined") return; const handleStorageChange = (e) => { if (e.key === "wishlist") { setWishlist(e.newValue ? JSON.parse(e.newValue) : []); } }; window.addEventListener("storage", handleStorageChange); return () => window.removeEventListener("storage", handleStorageChange); }, []); // 封装加入心愿单方法,操作时同时更新状态和存储 const addToWishlist = (product) => { // 去重判断,避免重复添加 if (wishlist.find(item => item.id === product.id)) return; const newWishlist = [...wishlist, product]; // 先更新本地状态,组件立即重渲染 setWishlist(newWishlist); // 再同步更新localStorage localStorage.setItem("wishlist", JSON.stringify(newWishlist)); }; // 封装移出心愿单方法 const removeFromWishlist = (productId) => { const newWishlist = wishlist.filter(item => item.id !== productId); setWishlist(newWishlist); localStorage.setItem("wishlist", JSON.stringify(newWishlist)); };
用户点击爱心触发对应的新增/移除方法时,状态会立即更新,爱心计数同步变化,不需要刷新页面,也不会出现无限循环的问题。
内容的提问来源于stack exchange,提问作者Rinael
相关产品推荐
相关产品推荐

