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

React使用useEffect、useState时首次加载页面数据不渲染问题

问题原因
  • refreshHandler 中的 XMLHttpRequest 是异步操作,你没有等待所有请求返回就提前执行了 setCoins。此时请求尚未完成,coin.price 还没有被赋值,更新到 state 里的数据没有价格字段,首次渲染自然不显示。点击刷新按钮时能正常显示,是因为上一轮的异步请求已经修改了内存中 coin 对象的属性,这一轮执行 setCoins 时就带上了之前拿到的价格。
  • useEffect 不支持直接传入 async 函数,async 函数返回的是 Promise 而非 useEffect 要求的清理函数,会导致React报错,也无法正确等待异步操作执行完成。
  • 直接修改 props 传入的 tickerSymbol 数组中的对象不符合 React 单向数据流规范,props 是只读属性,直接修改原始引用可能引发不可预期的副作用。
  • state 初始化存在逻辑错误:如果 props.tickerSymbol 本身是币种数组,useState([props.tickerSymbol]) 相当于在外面多套了一层数组,虽然你后续在 refreshHandler 里覆盖了这个错误的初始值,但首次渲染会存在结构不匹配的问题。
修复方案
  1. 首先调整 state 初始化逻辑,去掉多余的数组嵌套:
const [coins, setCoins] = useState(props.tickerSymbol);
  1. 将异步请求改为 Promise 封装,等待所有接口请求完成后再统一更新 state,不要直接修改原始 props 对象,而是基于返回结果创建新的对象:
const refreshHandler = async () => {
  // 遍历所有币种生成请求Promise
  const requestPromises = coinData.map(async (coin) => {
    const ApiUrl = `https://api.coingecko.com/api/v3/simple/price?ids=${coin.name}&vs_currencies=usd`;
    const response = await fetch(ApiUrl);
    const data = await response.json();
    // 不修改原对象,返回新的对象
    return {
      ...coin,
      price: data[coin.name]?.usd || 0
    };
  });
  // 等待所有请求完成
  const newCoins = await Promise.all(requestPromises);
  // 统一更新state
  setCoins(newCoins);
  newCoins.forEach(coin => console.log(coin.price));
};
  1. 修正 useEffect 的写法,内部定义异步函数再调用:
useEffect(() => {
  const initData = async () => {
    await refreshHandler();
  };
  initData();
}, []);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 23:57:01