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

如何从React自定义Hook返回数据?调用报Invalid hook call错误如何解决

问题原因
  • 违反React Hook官方调用规则:Hook仅可在函数组件的顶层作用域调用,禁止在事件回调、循环、条件分支、普通JavaScript函数内部调用。你将自定义HookuseFetchNGSData放在了事件处理函数handleGetPlayers内部,还嵌套在forEach循环中,因此触发非法Hook调用报错。
  • 你的自定义Hook本身结构不存在问题,错误完全由不合规的调用方式导致。
修复方案

如果你需要手动触发请求(比如点击按钮后拉取数据,同时遍历多个teamId批量请求),需要先调整自定义Hook的逻辑,将请求方法暴露出来供外部手动调用,而非默认挂载时自动执行请求:

修改后的自定义Hook代码

import { useState, useCallback } from "react";
const axios = require('axios');
const crypto = require('crypto');

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

    const dateString = () => {
        // 原有逻辑保持不变
        return date.toString();
    }

    // 把请求逻辑封装为可手动调用的方法
    const fetchData = useCallback(async (endpoint) => {
        setLoading(true);
        setError(null);
        try {
            const ngs_username = process.env.REACT_APP_NGS_USERNAME;
            const ngs_password = process.env.REACT_APP_NGS_PASSWORD;
            const ngs_access_token = process.env.REACT_APP_NGS_ACCESS_TOKEN;
            const ngs_secret_key = process.env.REACT_APP_NGS_SECRET_KEY;
            
            const string_to_sign = ngs_username + ngs_password + ngs_access_token + dateString();
            const digest = crypto.createHmac('sha1', ngs_secret_key).update(string_to_sign).digest('base64');
            const authKey = 'NGS ' + ngs_access_token + ':' + digest;
            
            const baseUrl = 'https://api.ngs.com';
            axios.defaults.headers.common['Authorization'] = authKey;
            const response = await axios.get(baseUrl + endpoint);
            setData(response.data);
            return response.data;
        } catch (err) {
            setError(err);
            console.error(err);
        } finally {
            setLoading(false);
        }
    }, [])

    return { data, loading, error, fetchData };
}

export default useFetchNGSData;

组件调用代码修改

将自定义Hook放在组件顶层调用,事件回调中仅调用Hook返回的fetchData方法执行请求:

import React, { useState } from 'react';
import useFetchNGSData from '../useFetchNGSData';

const Data = (props) => {
    const [players, setPlayers] = useState([]);
    // Hook必须放在组件顶层作用域调用
    const { fetchData } = useFetchNGSData();

    const handleGetPlayers = async () => {
        const allPlayers = [];
        // 遍历所有队伍ID批量请求数据
        for (const teamId of teamCollection) {      
            const teamRoster = await fetchData(`/league/roster/current?teamId=${teamId}`);
            teamRoster && allPlayers.push(...teamRoster);
        }
        setPlayers(allPlayers);
    }

    return (
        <div>
            <button onClick={handleGetPlayers}>获取玩家列表</button>
            {/* 玩家列表渲染逻辑 */}
        </div>
    );
}

export default Data;

如果你不需要手动触发,只需要在参数变化时自动拉取数据,直接将动态endpoint作为参数传入顶层调用的Hook即可,无需调整Hook原有结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 20:15:08