Next.js项目中Provider内部更新函数丢失前序状态问题排查
问题根因
- 错误将更新函数存入了state状态
你把updateCoupon、updateDeliveryPersion两个状态更新方法也放到了state中存储。第一次调用更新方法修改状态后,新的state里保留的是首次渲染时创建的旧更新函数,这些旧函数的闭包永远捕获的是初始状态值(deliveryPersion为own、coupon为空对象)。后续再调用任何更新方法时,都是基于初始状态做合并,自然会覆盖之前修改的其他状态。 - 状态更新未使用函数式写法,存在闭包陷阱
你的更新方法中直接用...state合并状态,当更新逻辑依赖上一次的状态值时,这种写法很容易因为闭包拿到旧的状态值,导致更新异常。
修复方案
首先不要把更新函数放到state中存储,Context的value可以直接组合状态和方法,不需要把方法存入state。其次更新状态时使用函数式写法获取最新的前序状态,避免闭包问题。
修正后的代码参考:
import {createContext, useContext, useState} from 'react' // 创建Context对象 const CartContext = createContext({ deliveryPersion:'own', coupon:{}, updateCoupon: (obj) => {}, updateDeliveryPersion: (type) => {}, }) // 导出Provider export function CartProvider(props) { // 仅将业务数据存入state,不存储更新函数 const [state, setState] = useState({ deliveryPersion:'own', coupon:{} }) const updateCoupon = (_coupon) => { // 函数式更新获取最新的前序状态 setState(prevState => ({...prevState, coupon: _coupon})) } const updateDeliveryPersion = (type) => { setState(prevState => ({...prevState, deliveryPersion: type})) } // 组装Context的value,组合状态和更新方法 const contextValue = { ...state, updateCoupon, updateDeliveryPersion } return ( <CartContext.Provider value={contextValue}> {props.children} </CartContext.Provider> ) } // 导出useContext钩子 export function useCartContext() { return useContext(CartContext); }
内容的提问来源于stack exchange,提问作者S.M_Emamian
相关产品推荐
相关产品推荐

