React useReducer存储购物车到localStorage始终少1条数据如何解决
问题现象
React项目实现购物车localStorage持久化功能时出现存储异常:实际添加N件商品到购物车时,localStorage中仅成功存储N-1件,具体规律为添加2件仅保存1件、添加3件仅保存2件、添加4件仅保存3件,成功存储的商品数始终比实际添加数量少1。
问题复现代码
const [state, dispatch] = useReducer(StoreReducer, { cart: JSON.parse(localStorage.getItem("cart")) || [], }); const addToCart = (product) => { dispatch({ type: "ADD_TO_CART", payload: product, }); localStorage.setItem("cart", JSON.stringify(state.cart)); };
问题根因
你踩了React状态更新的闭包陷阱:
useReducer的dispatch方法触发状态更新后,不会同步修改当前函数作用域内的state变量,当前作用域里的state仍然是更新前的旧值- 你在dispatch后立刻读取
state.cart,拿到的永远是还没加入当前新商品的旧购物车数据 - 把这份旧数据写入localStorage,自然每次都会少存最新添加的那1件商品
修复方案
移除addToCart方法里直接写入localStorage的逻辑,改用useEffect监听购物车状态变化,等组件完成渲染、state更新为最新值之后,再执行持久化操作,修复后完整代码如下:
import { useReducer, useEffect } from 'react'; const [state, dispatch] = useReducer(StoreReducer, { cart: JSON.parse(localStorage.getItem("cart")) || [], }); // 监听cart状态变化,状态更新完成后自动同步到localStorage useEffect(() => { localStorage.setItem("cart", JSON.stringify(state.cart)); }, [state.cart]); const addToCart = (product) => { dispatch({ type: "ADD_TO_CART", payload: product, }); };
注意:React中
useState、useReducer触发的所有状态更新都存在异步渲染特性,所有依赖最新state的副作用逻辑,都应该放在useEffect中监听对应state变化后执行,避免拿到闭包缓存的旧值导致逻辑异常。
内容的提问来源于stack exchange,提问作者Elue Wisdom
相关产品推荐
相关产品推荐

