React中dictionary打印正常取值返回undefined及state更新问题
问题定位与修复方案
核心问题1:map回调无返回值导致state更新为undefined
你代码中setBuys对应的map逻辑里,用花括号包裹了返回对象但没有写return语句,此时花括号会被识别为函数体块,map遍历每一项都会返回undefined,最终state会被更新为全undefined的数组,自然无法读取到预期值。
原错误代码:
setBuys( buys.map( b => { {...b, ...newDictionary[b.asset]} } ) )
修复方式:用括号包裹对象实现隐式返回,或手动添加return语句:
setBuys( buys.map( b => ({...b, ...newDictionary[b.asset]}) ) )
核心问题2:useEffect无依赖数组导致定时器重复创建
当前useEffect没有传入第二个依赖参数,会在每次组件渲染完成后都执行,每次运行都会创建新的60s定时器,最终会出现大量重复请求,还会引发内存泄漏。
修复方式:给useEffect添加依赖数组,若buys不会动态变化就传空数组,仅在组件挂载时执行一次;若buys会动态更新就把buys加入依赖数组,每次buys变化时自动销毁旧定时器、创建新定时器:
useEffect(() => { // 原有逻辑 }, []) // 空依赖仅挂载执行一次,buys可变时改为[buys]
核心问题3:闭包捕获旧state导致更新异常
你在setBuys时直接使用了当前作用域下的buys变量,这个变量是useEffect运行时捕获的旧值,如果buys之前发生过变更,会基于旧值更新,出现状态不同步问题。
修复方式:使用setState的函数式更新语法,永远拿到最新的state值:
setBuys(prevBuys => prevBuys.map(b => ({...b, ...newDictionary[b.asset]})) )
补充说明(早期异步map读取空的原因)
你最开始没有使用Promise.all的版本,直接执行buys.map(async buy => {})时,返回的是Promise数组,所有异步请求还未执行完成你就立刻读取newDictionary,此时对象还是空的。浏览器控制台打印的对象是引用类型,后续异步完成填充后你展开控制台才会看到值,实际同步读取时没有内容,你后续改用Promise.all等待所有异步完成再处理是正确的写法。
完整修复后的代码
useEffect(() => { const refreshData = async() => { const d = await Promise.all( buys.map(async buy => { const data = await queryCoinGeckoAPI(buy); const market_price = data.market_data.current_price.aud; const price_change = data.market_data.price_change_24h_in_currency.aud; const price_change_percentage = data.market_data.price_change_percentage_24h_in_currency.aud; const profit = buy.units === 0 || buy.price === 0 ? 0 : market_price * buy.units - buy.price; return { asset: buy.asset, market_price, price_change, price_change_percentage, profit }; }) ) const newDictionary = Object.fromEntries(d.map(item => [item.asset, item])); setBuys(prevBuys => prevBuys.map(b => ({...b, ...newDictionary[b.asset]})) ) } const interval = setInterval(refreshData, 60000); // 组件挂载先执行一次,无需等待60秒 refreshData(); return () => clearInterval(interval); }, [buys])
内容的提问来源于stack exchange,提问作者foo.d
相关产品推荐
相关产品推荐

