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

React自定义useFetchQL Hook重复请求问题:单次查询触发700+次调用求助

问题原因与解决方案

问题原因

  1. 自定义Hook未控制请求执行时机:useFetchQL直接在Hook顶层调用getData(),每次组件渲染(包括初始渲染、状态更新触发的重渲染)都会执行该函数发起新请求。而setData更新状态又会触发组件重渲染,形成循环,导致大量重复请求。
  2. App组件错误使用Hook返回值:用setChars(useFetchQL(...))的写法完全违规,setChars会触发App组件重渲染,重渲染又会再次调用useFetchQL,进一步加剧重复请求问题,同时不符合React Hook的使用规范。

解决步骤

  1. 在useFetchQL中用useEffect包裹请求逻辑,设置空依赖数组,确保请求仅在Hook挂载时执行一次。
  2. 修正App组件用法:直接接收useFetchQL返回的状态,无需额外维护chars状态。
  3. 修正参数类型不匹配问题:原Hook参数定义为URL类型,调用时传入的是字符串,调整参数类型为string避免类型报错。

修改后的代码

自定义Hook useFetchQL.ts

import { useState, useEffect } from 'react';

export const useFetchQL = (url: string): Array<Object> => {
    const [data, setData] = useState([]);

    const getData = async () => {
        const query = `
        query {
          characters{
            id 
            name 
            title 
            imageURL 
            leaderSkill 
            passive 
            categories 
            links
          }
        }`;
        try {
            const response = await fetch(url, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Accept": "application/json"
                },
                body: JSON.stringify({ query }),
            });
            const result = await response.json();
            setData(result.data.characters);
        } catch (error) {
            console.error("请求出错:", error);
        }
    };

    // 仅在组件挂载时执行一次请求
    useEffect(() => {
        getData();
    }, []);

    return data;
};

App组件

import './App.css';
import Cards from './components/Cards';
import Team from './components/Team';
import Search from './components/Search';
import { AddToTeamProvider } from './context/addToTeamContext';
import { useFetchQL } from './hooks/useFetchQL';

function App() {
    const chars = useFetchQL('https://dokkanapi.azurewebsites.net/graphql');
    console.log(chars);

    return (
        <div className="App">
            <AddToTeamProvider>
                <Team />
                <Search />
                <Cards chars={chars} /> {/* 若Cards组件需要数据,需传递该props */}
            </AddToTeamProvider>
        </div>
    );
}

export default App;

额外说明

  • 新增try/catch捕获请求异常,避免请求失败导致页面崩溃。
  • 若后续需要根据特定条件重新发起请求,只需在useEffect的依赖数组中添加对应变量(比如查询参数变化时重新请求)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 13:16:01