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

React中API重复请求及元素识别问题求助

问题解决:API重复请求与多次日志输出优化

问题分析

  1. API重复请求:你的useEffect依赖数组为空,理论上仅在组件挂载时执行一次,但开发环境下React Strict Mode会强制双调用useEffect(用于检测副作用),这是预期行为;若生产环境仍有重复请求,需检查组件是否被重复挂载(如路由配置、父组件重渲染导致卸载再挂载)。
  2. 多次日志输出:组件每次重渲染(setData/setLoading/setError触发时)都会执行函数体代码,包括价格计算和console.log,因此会多次打印;初始data为null,所以第一次输出undefined。
  3. 请求限制:重复请求(尤其是开发环境双调用+组件重复挂载)会导致短时间内请求次数超限。

解决方案

1. 给请求添加取消控制器,避免无效请求

给fetch加上AbortController,组件卸载时取消未完成的请求,同时忽略取消操作的错误:

import { useState, useEffect, useMemo } from "react";

function App() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

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

    fetch("http://localhost:4500/coingeckotest", { signal })
      .then(response => {
        if (response.ok) {
          return response.json();
        }
        throw response;
      })
      .then(fetchedData => {
        setData(fetchedData);
      })
      .catch(error => {
        // 忽略取消请求的错误
        if (error.name !== "AbortError") {
          console.error("Error fetching data: ", error);
          setError(error);
        }
      })
      .finally(() => {
        setLoading(false);
      });

    // 组件卸载时取消请求
    return () => controller.abort();
  }, []);

2. 用useMemo缓存价格计算结果,避免重复执行find

每次重渲染时find操作会重复执行,用useMemo缓存计算结果,仅在data变化时重新计算:

const { uniprice, sushiprice, curveprice, quickprice } = useMemo(() => {
    if (!data) {
      return {
        uniprice: undefined,
        sushiprice: undefined,
        curveprice: undefined,
        quickprice: undefined
      };
    }

    const uniswap = data[0].tickers?.find(donne => 
      donne.trade_url === "https://app.uniswap.org/#/swap?inputCurrency=0x2260fac5e5542a773aa44fbcfedf7c193bc2c599&outputCurrency=ETH"
    );
    const sushiswap = data[1].tickers?.find(donne => 
      donne.trade_url === "https://app.sushi.com/swap?inputCurrency=0x2260fac5e5542a773aa44fbcfedf7c193bc2c599&outputCurrency=ETH"
    );
    const curvefinance = data[2].tickers?.find(donne => donne.base === "DAI");
    const quickswap = data[3].tickers?.find(donne => 
      donne.trade_url === "https://quickswap.exchange/#/swap?inputCurrency=0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270&outputCurrency=0xbbba073c31bf03b8acf7c28ef0738decf3695683"
    );

    return {
      uniprice: uniswap?.converted_last?.usd,
      sushiprice: sushiswap?.converted_last?.usd,
      curveprice: curvefinance?.converted_last?.usd,
      quickprice: quickswap?.converted_last?.usd
    };
  }, [data]);

3. 仅在数据更新时打印日志

把console.log放到监听data变化的useEffect里,避免每次重渲染都打印:

useEffect(() => {
    if (data) {
      console.log(uniprice, sushiprice, curveprice, quickprice);
    }
  }, [data, uniprice, sushiprice, curveprice, quickprice]);

  if (loading) return "Loading...";
  if (error) return "Error !";

  return (
    <>
      {/* 在这里渲染价格数据,比如: */}
      <div>Uniswap Price: {uniprice}</div>
      <div>Sushiswap Price: {sushiprice}</div>
      <div>Curve Price: {curveprice}</div>
      <div>Quickswap Price: {quickprice}</div>
    </>
  );
}

export default App;

额外说明

  • 开发环境下的双调用useEffect是React Strict Mode的特性,用于检测潜在的副作用问题,生产环境编译后会自动移除该行为。
  • 若仍存在生产环境重复请求,检查App组件是否被嵌套在频繁重渲染的父组件中,或路由配置是否导致组件重复挂载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:43:57