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

React项目调用CoinGecko API遇CORS标头缺失错误求助

解决React调用CoinGecko API的CORS错误

你遇到的CORS错误是浏览器同源策略限制导致的——直接从http://localhost:3000访问CoinGecko API时,对方服务器未返回允许跨域的响应头。下面是几种可行的解决方法:

方法1:校验API地址与请求配置

首先确认CoinList函数生成的请求URL完全正确,可直接在浏览器地址栏访问该URL,验证是否能正常返回JSON数据。同时删除axios请求中的crossDomain: true配置(浏览器环境下该参数无效,反而可能干扰请求):

const fetchCoins = async () => {
  setLoading(true);
  try {
    // 移除crossDomain配置
    const { data } = await axios.get(CoinList(currency));
    setCoins(data);
  } catch (error) {
    console.error("Error fetching coins:", error);
  } finally {
    setLoading(false);
  }
};

方法2:配置React开发代理

通过本地代理转发请求,绕过浏览器的CORS限制,步骤如下:

  1. 安装代理依赖:
npm install http-proxy-middleware --save-dev
  1. 在项目根目录的src文件夹下创建setupProxy.js文件,添加代理配置:
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/coingecko-api',
    createProxyMiddleware({
      target: 'https://api.coingecko.com/api/v3',
      changeOrigin: true,
      pathRewrite: {
        '^/coingecko-api': '', // 移除前缀,转发到目标API地址
      },
    })
  );
};
  1. 修改请求地址为代理路径,比如调整CoinList函数或直接修改请求URL:
// 假设原来的CoinList返回完整API地址,现在改为代理路径
const CoinList = (currency) => 
  `/coingecko-api/coins/markets?vs_currency=${currency}&order=market_cap_desc&per_page=100&page=1&sparkline=false`;
  1. 重启React开发服务器,代理自动生效。

方法3:确认API访问限制

CoinGecko公开API支持无密钥访问,但有请求频率限制(每分钟10-30次)。如果上述方法无效,可检查是否触发了频率限制,或者尝试在请求中添加Accept: application/json头:

const { data } = await axios.get(CoinList(currency), {
  headers: {
    'Accept': 'application/json'
  }
});

修改后的完整组件代码示例

import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { CoinList } from '../config/api';
import { CrytpoState } from '../CryptoContext';
import { Container, LinearProgress, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, ThemeProvider, Typography, createTheme, makeStyles } from '@material-ui/core';
import { useNavigate} from "react-router-dom";


const CoinsTable = () => {

  const [coins, setCoins] = useState([]);
  const [loading, setLoading] = useState(false);
  const [search, setSearch] = useState("");
  const history=useNavigate();

  const {currency}=CrytpoState();

  const fetchCoins = async () => {
    setLoading(true);
    try {
      // 移除crossDomain配置,添加请求头(可选)
      const { data } = await axios.get(CoinList(currency), {
        headers: {
          'Accept': 'application/json'
        }
      });
      setCoins(data);
    } catch (error) {
      console.error("Error fetching coins:", error);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchCoins();
  }, [currency])
  

  const darkTheme= createTheme({
    palette:{
      primary:{
        main:"#fff",
      },
      type:"dark",
    },
  });


 const handleSearch=()=>{
  return coins.filter(
    (coin)=>
    coin.name.toLowerCase().includes(search.toLowerCase()) || coin.symbol.toLowerCase().includes(search.toLowerCase())
  );
 };

const useStyles=makeStyles(()=>({
  row:{
    cursor: 'pointer',
    '&:hover': {
      backgroundColor: '#131111'
    }
  },
}));
const classes=useStyles();

  return (
    <ThemeProvider theme={darkTheme}>
    <Container style={{
      textAlign:"center"
    }}>
      <Typography 
      variant="h4"
      style={{
        margin:18,
        fontFamily:"Montserrat",
      }}>
        CryptoCurrency Prices by Market Cap!
      </Typography>

      <TextField label="Search For a Crypto Currency..!" variant="outlined" 
        style={{
          marginBottom:20,
          width:"100%"
          }}
          onChange={(e)=>setSearch(e.target.value)}
      />

      <TableContainer>
        {loading?(
          <LinearProgress style={{backgroundColor:"gold"}} />
        ) :(
         <Table>
          <TableHead style={{backgroundColor:"#EEBC1D"}}>
            <TableRow>
            {["Coin","Price","24h Change","Market Cap"].map((head)=>(
              <TableCell
              style={{
                color:"black",
                fontWeight:700,
                fontFamily:"Montserrat", 
              }}
              key={head}
              align={head==="Coin"? "": "right"}
              >{head}</TableCell>
         ))}

            </TableRow>
          </TableHead>
          <TableBody>
          {handleSearch().map((row)=>{
            const profit=row.price_change_percentage_24h>0;
            return(
              <TableRow onClick={()=>history(`/coins/${row.id}`)}
              className={classes.row}
              key={row.id}>

              <TableCell 
              component="th"
              scope="row"
              style={{
                display:"flex",
                gap:15,

              }}>
              <img
                src={row?.image}
                alt={row.name}
                height="50"
                style={{
                  marginBottom:10
                }}
              />
              <div
              style={{
                display:"flex",
                flexDirection:"column",
              }}>
                <span style={{
                  textTransform:"uppercase",
                  fontSize:22,
                }}>
                  {row.symbol}
                </span>
                <span
                style={{color:"darkgrey"}}>
                  {row.name}
                </span>
              </div>
              </TableCell>

              <TableCell align="right">
                {row.current_price.toLocaleString()} {currency}
              </TableCell>
              <TableCell 
                align="right"
                style={{
                  color: profit ? 'rgb(14, 203, 129)' : 'red',
                  fontWeight: 700
                }}>
                {profit ? '+' : ''}{row.price_change_percentage_24h.toFixed(2)}%
              </TableCell>
              <TableCell align="right">
                {row.market_cap.toLocaleString()} {currency}
              </TableCell>
               
              </TableRow>
            );

          })}

          </TableBody>
         </Table>
        )}
      </TableContainer>
    </Container>

    </ThemeProvider>
  )
}

export default CoinsTable;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:18:11