React中setState无法更新对象状态:嵌套值变更无效问题
问题分析与解决
你的代码问题出在直接修改了React状态对象的引用,React依赖浅比较判断状态是否变化:当你用let tempCardRootData = cardRouteData时,只是复制了原state对象的引用,修改这个副本的属性并没有创建新对象,所以setCardRouteData调用后,React认为前后cardRouteData是同一个对象,不会触发状态更新,也不会执行依赖cardRouteData的useEffect。
修复方案
需要创建原cardRouteData的新副本,修改属性后再更新状态,确保引用地址变化。可以用对象扩展运算符...实现:
const [comulatedTimeOnSpotArr, setComulatedTimeOnSpotArr] = useState([0, 3600, 20000]) const [cardRouteData, setCardRouteData] = useState({"duration":11450, "duration-with-stops":31145}) useEffect(() => { if (comulatedTimeOnSpotArr?.length > 0) { // 创建新对象副本,保留原有属性,仅修改目标属性 const newCardRouteData = { ...cardRouteData, "duration-with-stops": cardRouteData.duration + comulatedTimeOnSpotArr.at(-1) } setCardRouteData(newCardRouteData) } }, [comulatedTimeOnSpotArr, cardRouteData]) // 需将cardRouteData加入依赖,避免闭包导致的旧值问题 useEffect(() => { console.log('cardRouteData has changed', cardRouteData) }, [cardRouteData])
关键修改点
- 用
...cardRouteData创建原对象的浅拷贝,生成新的对象引用,让React能检测到状态变化 - 用
comulatedTimeOnSpotArr.at(-1)替代comulatedTimeOnSpotArr[comulatedTimeOnSpotArr.length -1],写法更简洁 - 将
cardRouteData加入第一个useEffect的依赖数组,因为代码中用到了cardRouteData.duration,避免闭包导致的旧值问题
另外要确保更新comulatedTimeOnSpotArr时传入新数组,比如:
// 正确的数组更新方式(创建新数组) setComulatedTimeOnSpotArr(prev => [...prev.slice(0, -1), 4000])
不要直接修改原数组(这种方式不会触发状态更新):
// 错误方式:直接修改原数组,React检测不到变化 comulatedTimeOnSpotArr[2] = 4000 setComulatedTimeOnSpotArr(comulatedTimeOnSpotArr)
内容的提问来源于stack exchange,提问作者JK2018
相关产品推荐
相关产品推荐

