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

React组件渲染后无法展示最高APY Reward的Vault信息

问题分析与修复方案

问题根源

  1. 普通变量无法触发组件重渲染:你用let poolDetails定义了普通变量,而非React状态。即使异步请求后更新了它的值,React无法感知到变化,不会触发组件重渲染,导致UI无法更新。
  2. 异步请求处理不健壮:手动用counter计数判断请求完成存在风险——若某一请求失败,counter永远到不了3,loading会一直处于true状态;另外toFixed(2)返回字符串,直接用Math.max虽能隐式转换,但易引发类型问题。
  3. 缺少请求清理机制:组件卸载时若请求未完成,会导致内存泄漏。

修复步骤

  1. 将poolDetails改为React状态,让React追踪其变化并触发重渲染。
  2. 使用Promise.all并行处理所有API请求,替代手动计数,统一处理成功/失败场景。
  3. 存储APY数值而非字符串,避免类型转换问题。
  4. 添加AbortController清理未完成的请求,防止内存泄漏。

修改后的完整代码

import { useState, useEffect } from 'react';
import type { PoolInfo } from './your-type-file-path'; // 替换为你的类型文件实际路径

export const FeaturedPool = () => {
  const [loading, setLoading] = useState(true);
  const [poolDetails, setPoolDetails] = useState<PoolInfo | undefined>(undefined);
  const [error, setError] = useState<string | undefined>(undefined);

  useEffect(() => {
    const abortController = new AbortController();
    const signal = abortController.signal;

    const fetchAndCalculateTopPool = async () => {
      try {
        // 筛选出稳定币池子
        const stablePools = POOLS?.filter(pool => pool.stableCoins) || [];
        if (stablePools.length === 0) {
          throw new Error("未找到稳定币池子");
        }

        // 并行请求所有池子的APY数据
        const apyPromises = stablePools.map(async (pool) => {
          if (!pool.targetedAPYId) throw new Error(`池子${pool.title}缺少targetedAPYId`);
          
          const response = await fetch(`https://yields.llama.fi/chart/${pool.targetedAPYId}`, { signal });
          if (!response.ok) throw new Error(`获取${pool.title}的APY数据失败`);
          
          const res = await response.json();
          const latestApyReward = res.data.at(-1)?.apyReward;
          if (typeof latestApyReward !== 'number') throw new Error(`${pool.title}的APY数据格式异常`);
          
          return {
            pool,
            apyReward: latestApyReward
          };
        });

        // 等待所有请求完成
        const apyResults = await Promise.all(apyPromises);
        
        // 找出APY最高的池子
        const topPool = apyResults.reduce((prev, current) => {
          return current.apyReward > prev.apyReward ? current : prev;
        }, apyResults[0]);

        setPoolDetails(topPool.pool);
      } catch (err) {
        setError(err instanceof Error ? err.message : "发生未知错误");
      } finally {
        setLoading(false);
      }
    };

    fetchAndCalculateTopPool();

    // 组件卸载时终止未完成的请求
    return () => abortController.abort();
  }, []);

  if (loading) return <p>加载中... </p>;
  if (error) return <p>错误:{error}</p>;
  if (!poolDetails) return <p>无可用池子数据</p>;

  return (
    <div className="featured-vault">
      <h3>{poolDetails.title}</h3>
      <p>APY奖励:{poolDetails.targetedAPY}</p>
      {/* 可扩展添加更多信息,比如描述、风险等级、TVL等 */}
    </div>
  );
};

关键改进点说明

  • 状态管理:用useState管理poolDetails,确保数据更新时组件自动重渲染。
  • 并行请求:Promise.all让所有请求同时执行,比逐个请求更高效,无需手动计数。
  • 错误处理:捕获请求失败、数据异常等情况,避免loading无限挂起,同时给用户明确的错误反馈。
  • 类型安全:明确检查数据类型,减少TypeScript报错,避免隐式类型转换带来的问题。
  • 内存泄漏防护:AbortController在组件卸载时终止未完成的请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 15:53:14