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
相关产品推荐
相关产品推荐

