使用React+Recharts+CoinGecko API时,if语句无法正确修改图表颜色
问题分析与修复方案
核心问题1:异步状态更新导致取值错误
你定义的pricesData函数里,调用setPricesIsUp后直接返回pricesIsUp,但React的setState是异步操作,此时返回的还是更新前的旧值,导致isUp始终拿不到正确的判断结果。
核心问题2:useLayoutEffect依赖错误引发无限循环
useLayoutEffect的依赖数组里加了isUp,而effect内部又调用setIsUp,这会导致组件无限重新渲染,同时干扰状态的正确更新。
核心问题3:价格对比顺序颠倒
CoinGecko的market_chart接口返回的prices数组是按时间从旧到新排列的,你现在取convertedData[0]作为今日数据、[1]作为昨日数据完全搞反了,直接导致涨跌判断错误。
修复后的完整代码
import React, { useLayoutEffect, useState } from 'react' import { XAxis, YAxis, AreaChart, Area } from 'recharts'; const ChartComponentM = ({ data, pricesData }) => { return ( <div className="place-self-center"> <AreaChart width={200} height={50} data={data}> <defs> <linearGradient id="colorUv" x1="0" y1="0" x2="0" y2="1"> <stop offset="1%" stopColor={pricesData ? "#17ff00" : "#ff0000"} stopOpacity={0.8} /> <stop offset="100%" stopColor={pricesData ? "#17ff00" : "#ff0000"} stopOpacity={0} /> </linearGradient> </defs> <Area fill="url(#colorUv)" dot={false} type="category" dataKey="prices" stroke="#000" strokeWidth="1px" /> <XAxis dataKey="date" hide /> <YAxis dataKey="prices" hide domain={["auto", "auto"]} /> </AreaChart> </div> ) } const Chart = ({ id }) => { const [chartDataM, setChartDataM] = useState() const [isUp, setIsUp] = useState(true) useLayoutEffect(() => { const getChartData = async (coinId) => { try { const response = await fetch( `https://api.coingecko.com/api/v3/coins/${coinId}/market_chart?vs_currency=usd&days=30&interval=daily` ); const data = await response.json(); // 转换数据格式,保留时间顺序 const convertedData = data.prices.map(item => ({ date: new Date(item[0]).toLocaleDateString(), prices: item[1] })); // 取最新两天数据:最后一个是今日,倒数第二个是昨日 const latestIndex = convertedData.length - 1; const todayPrice = convertedData[latestIndex].prices; const yesterdayPrice = convertedData[latestIndex - 1].prices; // 直接判断涨跌,无需中间状态 const priceIsUp = todayPrice > yesterdayPrice; setIsUp(priceIsUp); setChartDataM(convertedData); console.log("今日价格:", todayPrice); console.log("昨日价格:", yesterdayPrice); console.log("价格是否上涨:", priceIsUp); } catch (error) { console.error("获取图表数据失败:", error); } } getChartData(id); }, [id]) // 仅依赖id,避免无限循环 return ( <div className='place-self-center'> {chartDataM && <ChartComponentM data={chartDataM} pricesData={isUp} />} </div> ) } export default Chart
关键修复点说明
- 移除冗余状态:删掉
pricesIsUp中间状态,直接计算涨跌结果,规避异步更新的坑。 - 修正价格对比逻辑:按照API返回的时间顺序,取数组最后两个元素做对比,确保涨跌判断正确。
- 清理effect依赖:去掉
isUp作为依赖,只保留id,解决无限循环问题。 - 增加加载判断:渲染子组件前先判断
chartDataM是否存在,避免初始空数据报错。 - 优化异步代码:用
async/await替代链式then,代码更清晰易读。
内容的提问来源于stack exchange,提问作者imnotremi
相关产品推荐
相关产品推荐

