You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

关键修复点说明

  1. 移除冗余状态:删掉pricesIsUp中间状态,直接计算涨跌结果,规避异步更新的坑。
  2. 修正价格对比逻辑:按照API返回的时间顺序,取数组最后两个元素做对比,确保涨跌判断正确。
  3. 清理effect依赖:去掉isUp作为依赖,只保留id,解决无限循环问题。
  4. 增加加载判断:渲染子组件前先判断chartDataM是否存在,避免初始空数据报错。
  5. 优化异步代码:用async/await替代链式then,代码更清晰易读。

内容的提问来源于stack exchange,提问作者imnotremi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 21:11:07