reactjs - 执行 axios 请求的自定义钩子 [React, Typescript]
问题描述
我正在尝试创建一个可重用的自定义钩子(useRequest),我可以在其中使用 axios 获取数据,显示它并具有加载状态。如果出现错误,我希望它被 useRequest 捕获。我无法捕获最终错误并将 axios 请求传递给 useRequest。目前我只得到空的错误消息。
编辑:我使用生成的 api,它使用 axios。因此,要发出我的 fetch 请求,它看起来像这样:
import {GeneratedApi} from '/generatedApi'
const generatedApi = new GeneratedApi(configuration) //configuration is for editing the headers etc.
const response = await generatedApi.getData();
setData(response.data);
我的代码:
import axios, { AxiosResponse } from "axios";
import { useEffect, useState } from "react";
const useRequest = (promise: Promise<AxiosResponse<any>>) => {
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
setError(null);
await promise;
setLoading(false);
setError(null);
} catch (error) {
setLoading(false);
setError("Error: " + JSON.stringify(error));
}
};
fetchData();
}, [promise]);
return [loading, error];
};
export default function App() {
const [data, setData] = useState<any | null>(null);
const [loading, error] = useRequest(async () => {
const response = await axios.get("https://jsonplaceholder.typicode.com/todos");
setData(response.data);
return response;
});
if (loading) {
return <p>Loading ...</p>;
} else if (data) {
return <p>{data}</p>;
} else {
return <p>Error: {error}</p>;
}
}
解决方案
您可以传递一个包含在 useCallback 钩子中的函数,该函数将调用您的 api 调用:
import axios, { AxiosResponse } from "axios";
import { useCallback, useEffect, useState } from "react";
const url = "https://jsonplaceholder.typicode.com/todos"
const useRequest = (apiCall: () => Promise<AxiosResponse<any>>, setData: (data: any) => void) => {
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
setError(null);
const response = await apiCall()
setData(response.data)
setLoading(false);
setError(null);
} catch (error) {
setLoading(false);
setData(null)
setError("Error: " + JSON.stringify(error));
}
};
fetchData();
}, [apiCall, setData]);
return [loading, error];
};
export default function App() {
const [data, setData] = useState<any | null>(null);
const fun = useCallback(() => axios.get(url), [])
const [loading, error] = useRequest(fun, setData);
if (loading) {
return <p>Loading ...</p>;
} else if (data) {
return <p>{'data'}</p>;
} else {
return <p>Error: {error}</p>;
}
}
推荐阅读
- css - /deep/ 概念多页效果相同的 scss 。但我不希望角度中的一页效果
- python - Python 请求很慢并且需要很长时间才能完成 HTTP 或 HTTPS 请求
- sql-server - 多个 sql 作业成功时发送电子邮件通知
- javascript - React.js 使用地图时创建新行
- c++ - 当该数组的索引中没有元素时,指针指向的是什么?
- docker - 是否可以将 awslog 与 gitlab-ci 自动缩放运行器一起使用?
- typescript - 在 Typescript 中返回 Promise 的 Promise 不会编译
- python - 无法使用 Selenium 访问站点 https://www.sahbinden.com
- c# - 从远程进程获取标准输入
- html - 元素意外占据了其容器的整个高度