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

NextJS+Solidity项目部署Fleek后axios.get失效求助

问题分析与解决方案

核心问题定位

你的Cards组件存在两个关键问题:

  1. 直接在组件渲染流程中调用异步函数updateUI,每次组件状态更新(如setImageHash/setName)都会重新执行组件代码,触发updateUI形成无限重渲染循环。本地开发环境因缓存或宽松规则未暴露问题,但Fleek生产环境的优化会放大该问题,导致请求被浏览器或边缘节点限制。
  2. 未规范处理异步请求的生命周期,违反React渲染逻辑。

修复步骤

1. 规范异步调用逻辑(使用useEffect)

将updateUI放入useEffect钩子,仅在ipfs参数变化时执行,避免无限调用:

import { useState, useEffect } from "react"
import axios from 'axios'

export default function Cards({ ipfs, tokenId }) {
    
    function handleClick() {
        localStorage.setItem("Index Clicked", tokenId);
        document.getElementById("hideNavbar").style.display = 'flex';
    }

    const [imageHash, setImageHash] = useState(ipfs);
    const [name,setName] = useState(null);
    
    useEffect(() => {
        async function updateUI(){
            console.log(ipfs);
            try {
                const response = await axios.get(`https://ipfs.io/ipfs/${ipfs}`);
                setImageHash(response.data.imageHash);
                setName(response.data.name);
            } catch (error) {
                console.error('IPFS请求失败:', error);
            }
        }
        if(ipfs){
            updateUI();
        }
    }, [ipfs]); // 仅当ipfs变化时执行

    let extension = ""
    
    if(name!=null){
        extension = name.slice(name.indexOf('.') + 1,);
    }
    
    return (
        <div className="card select" onClick={handleClick}>
            <div className="top-left"></div>
            <div className="extension">{extension}</div>
            <div className="name">{name}</div>
            {imageHash ? <div className="ipfs">IPFS: {imageHash.slice(0, 4)}...{imageHash.slice(40,)}</div> : <div>Hash unavailable..</div>}
        </div>
    )
}

2. 优化Fleek部署配置

  • 添加CORS配置到next.config.js,避免跨域限制:
module.exports = {
  async headers() {
    return [
      {
        source: '/api/:path*',
        headers: [
          { key: 'Access-Control-Allow-Credentials', value: 'true' },
          { key: 'Access-Control-Allow-Origin', value: '*' },
          { key: 'Access-Control-Allow-Methods', value: 'GET,OPTIONS,PATCH,DELETE,POST,PUT' },
          { key: 'Access-Control-Allow-Headers', value: 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version' },
        ],
      },
    ];
  },
};
  • 替换IPFS网关:若https://ipfs.io访问不稳定,可改用https://cloudflare-ipfs.com或https://gateway.pinata.cloud。

axios替代方案

1. 原生Fetch API(无额外依赖)

直接使用浏览器原生API实现请求:

useEffect(() => {
    async function updateUI(){
        if(!ipfs) return;
        try {
            const response = await fetch(`https://ipfs.io/ipfs/${ipfs}`);
            const data = await response.json();
            setImageHash(data.imageHash);
            setName(data.name);
        } catch (error) {
            console.error('请求失败:', error);
        }
    }
    updateUI();
}, [ipfs]);

2. SWR(NextJS推荐方案)

自带缓存、重新验证功能,适合NextJS项目:
首先安装依赖:

npm install swr

修改组件代码:

import { useState } from "react"
import useSWR from 'swr'

const fetcher = async (url) => {
    const res = await fetch(url);
    return res.json();
};

export default function Cards({ ipfs, tokenId }) {
    
    function handleClick() {
        localStorage.setItem("Index Clicked", tokenId);
        document.getElementById("hideNavbar").style.display = 'flex';
    }

    const [imageHash, setImageHash] = useState(ipfs);
    const { data } = useSWR(ipfs ? `https://ipfs.io/ipfs/${ipfs}` : null, fetcher);
    
    const name = data?.name || null;
    
    useEffect(() => {
        if(data?.imageHash){
            setImageHash(data.imageHash);
        }
    }, [data]);

    let extension = ""
    
    if(name!=null){
        extension = name.slice(name.indexOf('.') + 1,);
    }
    
    return (
        <div className="card select" onClick={handleClick}>
            <div className="top-left"></div>
            <div className="extension">{extension}</div>
            <div className="name">{name}</div>
            {imageHash ? <div className="ipfs">IPFS: {imageHash.slice(0, 4)}...{imageHash.slice(40,)}</div> : <div>Hash unavailable..</div>}
        </div>
    )
}

3. TanStack Query(React Query)

功能强大的数据管理库,支持缓存、重试、背景更新:
首先安装依赖:

npm install @tanstack/react-query

在_app.js中配置全局Provider:

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();

function MyApp({ Component, pageProps }) {
  return (
    <QueryClientProvider client={queryClient}>
      <Component {...pageProps} />
    </QueryClientProvider>
  );
}

export default MyApp;

修改Cards组件:

import { useState, useEffect } from "react"
import { useQuery } from '@tanstack/react-query';

export default function Cards({ ipfs, tokenId }) {
    
    function handleClick() {
        localStorage.setItem("Index Clicked", tokenId);
        document.getElementById("hideNavbar").style.display = 'flex';
    }

    const [imageHash, setImageHash] = useState(ipfs);
    
    const { data } = useQuery({
        queryKey: ['ipfsData', ipfs],
        queryFn: async () => {
            const res = await fetch(`https://ipfs.io/ipfs/${ipfs}`);
            return res.json();
        },
        enabled: !!ipfs, // 仅当ipfs存在时执行请求
    });

    const name = data?.name || null;
    
    useEffect(() => {
        if(data?.imageHash){
            setImageHash(data.imageHash);
        }
    }, [data]);

    let extension = ""
    
    if(name!=null){
        extension = name.slice(name.indexOf('.') + 1,);
    }
    
    return (
        <div className="card select" onClick={handleClick}>
            <div className="top-left"></div>
            <div className="extension">{extension}</div>
            <div className="name">{name}</div>
            {imageHash ? <div className="ipfs">IPFS: {imageHash.slice(0, 4)}...{imageHash.slice(40,)}</div> : <div>Hash unavailable..</div>}
        </div>
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:17:11