如何在React函数中调用自定义useAxios Hook处理点击触发请求?
解决React中点击事件函数调用自定义Hook的问题
需求是在点击触发的handleNewSale函数中调用自定义Hook useAxios,但React不允许在普通函数内调用Hook,需要调整实现方式。
原自定义Hook代码
import { useState, useEffect } from "react"; import Axios from "axios"; const useAxios = (method: string, param: string, data: any) => { const [response, setResponse] = useState([]); const [error, setError] = useState([]); const fetchData = () => { Axios({ method: method, url: `https://gernagroup-server.herokuapp.com/${param}`, data: data, }) .then((response) => { setResponse(response.data); }) .catch((err) => { setError(err); }); }; useEffect(() => { fetchData(); }, []); return { response, error }; }; export default useAxios;
原点击事件函数及触发按钮
const handleNewSale = () => { Axios.post("https://gernagroup-server.herokuapp.com/new-sale", { data: selectedValues, }) .then((response) => { console.log(response); showModal(ResultType.success, "New sale added successfully!"); }) .catch((err) => { console.log(err); showModal(ResultType.error, "Something went wrong"); }); };
<Button text="New sale" onClick={handleNewSale} />
解决方法
1. 改造useAxios Hook,支持手动触发请求
原Hook会在组件挂载时自动执行请求,不符合点击触发的需求。我们移除自动执行逻辑,将请求函数暴露出来,让外部可以手动调用:
import { useState } from "react"; import Axios from "axios"; const useAxios = () => { const [response, setResponse] = useState<any>(null); const [error, setError] = useState<any>(null); const [isLoading, setIsLoading] = useState(false); // 可选:添加加载状态优化体验 const fetchData = async (method: string, param: string, data: any) => { setIsLoading(true); try { const res = await Axios({ method: method, url: `https://gernagroup-server.herokuapp.com/${param}`, data: data, }); setResponse(res.data); setError(null); } catch (err) { setError(err); setResponse(null); } finally { setIsLoading(false); } }; return { response, error, isLoading, fetchData }; }; export default useAxios;
2. 在组件中使用改造后的Hook
在组件顶层调用useAxios,拿到fetchData函数和状态,然后在handleNewSale中触发请求,通过监听状态变化处理弹窗逻辑:
import useAxios from "./path/to/useAxios"; // 组件内部 const { response, error, isLoading, fetchData } = useAxios(); // 监听响应和错误,处理弹窗 useEffect(() => { if (response) { console.log(response); showModal(ResultType.success, "New sale added successfully!"); } if (error) { console.log(error); showModal(ResultType.error, "Something went wrong"); } }, [response, error]); const handleNewSale = () => { // 调用fetchData发起请求 fetchData("post", "new-sale", { data: selectedValues }); };
关键说明
- React Hook必须在组件顶层或其他Hook中调用,因此我们将
useAxios放在组件顶层,拿到可手动触发的fetchData函数后,再在点击事件中调用这个函数。 isLoading状态可用于优化交互,比如点击按钮后禁用按钮直到请求完成。
内容的提问来源于stack exchange,提问作者KarolJ12
相关产品推荐
相关产品推荐

