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

React中在普通函数内调用useState/useEffect触发报错,如何通过按钮点击触发API请求?

解决按钮点击触发API请求时的React Hooks报错问题

你遇到的报错完全是因为违反了React Hooks的核心规则:React Hooks(比如useState、useEffect)只能在React函数组件的顶层作用域,或者自定义Hook函数的顶层作用域中调用,而clickCreate只是一个普通的事件回调函数,不符合这个要求,所以才会抛出错误。

要实现点击按钮触发API请求,其实不需要在回调里用useEffect,直接把状态放到组件内部,在点击回调里调用axios即可。下面是两种可行的方案:

方案一:基础实现(直接在组件内处理)

把状态定义在CreateButton组件内部,点击事件触发时直接发起API请求:

import axios from 'axios';
import { useState } from 'react';

const CreateButton = (props) =>{ 
  // 将状态放到组件的顶层作用域
  const [result, setResult] = useState([]);

  const clickCreate = (msg) => { 
    console.log(msg);
    // 点击时直接发起API请求
    axios.get('http://localhost:8000/api/genres/') 
      .then((res) => { 
        console.log(res.data.items); 
        setResult(res.data.items); 
      })
      .catch(err => {
        console.error('请求失败:', err);
      }); 
  }

  return( 
    <div> 
      <i 
        onClick={() => clickCreate("test")} 
        id="createBtn" 
        className="fas fa-5x fa-microphone-alt"
      ></i> 
    </div> 
  ); 
}

方案二:复用性优化(抽成自定义Hook)

如果你的API请求逻辑需要在多个组件里复用,或者想更好地处理加载、错误状态,可以把请求逻辑抽成一个自定义Hook:

import { useState } from 'react';
import axios from 'axios';

// 自定义Hook,封装请求逻辑
function useFetchGenres() {
  const [result, setResult] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const fetchGenres = () => {
    setLoading(true);
    axios.get('http://localhost:8000/api/genres/')
      .then((res) => {
        setResult(res.data.items);
        setError(null); // 请求成功时清空错误
      })
      .catch(err => {
        console.error('请求失败:', err);
        setError(err);
      })
      .finally(() => {
        setLoading(false); // 无论成功失败都结束加载状态
      });
  };

  // 返回状态和请求触发函数
  return { result, loading, error, fetchGenres };
}

// 在组件中使用自定义Hook
const CreateButton = (props) =>{ 
  const { result, loading, error, fetchGenres } = useFetchGenres();

  const clickCreate = (msg) => { 
    console.log(msg);
    fetchGenres(); // 调用Hook里的请求函数
  }

  return( 
    <div> 
      <i 
        onClick={() => clickCreate("test")} 
        id="createBtn" 
        className="fas fa-5x fa-microphone-alt"
      ></i>
      {/* 可以根据状态展示加载/错误提示 */}
      {loading && <span>正在加载...</span>}
      {error && <span className="error-text">请求出错:{error.message}</span>}
    </div> 
  ); 
}

这样既严格遵守了React Hooks的规则,又完美实现了点击按钮触发API请求的需求,还能更优雅地处理请求过程中的各种状态~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 03:54:07