useAxios:使用 axios 调用 API 的简单自定义钩子
大家好,
如果没有 API 调用,前端应用就不完整,调用 API 会变得有些重复。为此,我们可以创建一个自定义钩子,省去这种重复操作。从前端进行 API 调用,常用的方法有fetch和axios。由于 Axios 支持拦截器等功能,我们将在此钩子中使用它们。
我们将按照以下步骤创建useAxios 钩子
- 1. 使用 axios 从组件执行 API 调用。2
. 添加 API 响应、加载和错误状态。3
. 使用以上所有方法创建一个用于调用 API 的钩子。4
. 使钩子动态化,以调用所有类型的 API 方法。
如果您不想执行这些步骤并直接跳到最终代码,请查看此处。
现在,让我们一步一步深入创建我们的自定义钩子!
1. 从组件进行简单的 API 调用
为了创建此示例,我们将使用jsonplaceholder 的posts api。他们还创建了更多类似的 API,用于练习。
通常,一个应用程序的所有 API 都具有相同的基本 URL。我们将首先为 axios 设置基本 URL,这样就无需反复传递它。如果您使用多个基本 URL,axios 可以通过创建实例来支持。您可以查看其文档。
在我们的 App 组件中,我们只需调用一个getAPI 来获取帖子列表。为此,我们使用了useEffect钩子。App 组件的基本 API 调用如下所示:
//App Component
import { useEffect } from 'react';
import axios from 'axios';
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
const App = () => {
const fetchData = () => {
axios
.get('/posts')
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
};
useEffect(() => {
fetchData();
}, []);
return (
<div className='app'>
//do something
</div>
);
};
export default App;
上面的 API 调用很简单。我们以前axios.get调用 API 时,会使用 Promise 来获取结果或错误。因为我们已经设置了 baseURL,所以我们只需将具体路径传递给 axios 方法即可。
2. 向 API 调用添加不同的状态
但到目前为止,我们只是记录来自 API 的响应。让我们使用 React 的状态来保存响应和错误(如果发生)。此外,我们将添加一个加载状态,以便有条件地在页面上显示加载器。
// App Component
import { useState, useEffect } from 'react';
import axios from 'axios';
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
const App = () => {
const [response, setResponse] = useState(null);
const [error, setError] = useState('');
const [loading, setloading] = useState(true);
const fetchData = () => {
axios
.get('/posts')
.then((res) => {
setResponse(res.data);
})
.catch((err) => {
setError(err);
})
.finally(() => {
setloading(false);
});
};
useEffect(() => {
fetchData();
}, []);
return (
<div className='app'>
//do something
</div>
);
};
export default App;
3. 创建自定义钩子
自定义钩子一开始可能会让人不知所措。但是,如果你像其他组件一样看待它们,它们会更有意义。需要记住的是,自定义钩子只是另一个组件,它返回值而不是 JSX 。这是我对自定义钩子的定义,不知何故,它让我对这个概念更加清晰了。你可以在这里阅读更多关于自定义钩子的内容。
现在,让我们将调用 API 的逻辑从应用组件复制到自定义钩子中。因此,我们的初稿useAxios大致如下:
// useAxios hook (first draft)
import { useState, useEffect } from 'react';
import axios from 'axios';
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
const useAxios = () => {
const [response, setResponse] = useState(null);
const [error, setError] = useState('');
const [loading, setloading] = useState(true);
const fetchData = () => {
axios
.get('/posts')
.then((res) => {
setResponse(res.data);
})
.catch((err) => {
setError(err);
})
.finally(() => {
setloading(false);
});
};
useEffect(() => {
fetchData();
}, []);
// custom hook returns value
return { response, error, loading };
};
export default useAxios;
如果你仔细观察,就会发现我们实际上是复制粘贴了代码,并创建了一个自定义钩子。唯一的区别是,这个钩子返回了三个值:加载、响应和错误。
到目前为止,一切看起来都很好,但我们创建的钩子根本不是动态的。如果我们需要更改 API 路径,或者我们想使用 post 调用而不是 get 调用,那么我们现在无法做到。
因此,这是使我们的钩子更加灵活的最后一步。 -
4. 让钩子更加动态
为了使钩子动态化,我们可以为 URL 路径创建一个变量,并将其作为 prop 传递给钩子。此外,axios 可以支持 get、put、post 和 delete 等方法。因此,我们也需要一个方法名变量。除了路径和方法之外,我们还将添加两个变量,用于将正文和标头传递给请求。添加完这些之后,我们的钩子将如下所示:
最终代码
// useAxios hook
import { useState, useEffect } from 'react';
import axios from 'axios';
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
const useAxios = ({ url, method, body = null, headers = null }) => {
const [response, setResponse] = useState(null);
const [error, setError] = useState('');
const [loading, setloading] = useState(true);
const fetchData = () => {
axios[method](url, JSON.parse(headers), JSON.parse(body))
.then((res) => {
setResponse(res.data);
})
.catch((err) => {
setError(err);
})
.finally(() => {
setloading(false);
});
};
useEffect(() => {
fetchData();
}, [method, url, body, headers]);
return { response, error, loading };
};
export default useAxios;
useAxios钩子已准备就绪,现在让我们将其应用于我们的应用组件,并尝试使用它来创建新帖子。因此,该App组件将是 -
// App Component
const App = () => {
const { response, loading, error } = useAxios({
method: 'post',
url: '/posts',
headers: JSON.stringify({ accept: '*/*' }),
body: JSON.stringify({
userId: 1,
id: 19392,
title: 'title',
body: 'Sample text',
}),
});
const [data, setData] = useState([]);
useEffect(() => {
if (response !== null) {
setData(response);
}
}, [response]);
return (
<div className='App'>
<h1>Posts</h1>
{loading ? (
<p>loading...</p>
) : (
<div>
{error && (
<div>
<p>{error.message}</p>
</div>
)}
<div>{data && <p>{data.id}</p>}</div>
</div>
)}
</div>
);
};
export default App;
这是 useAxios hook 的最基础版本。您可以根据自己的需求添加更多自定义功能。
非常感谢你阅读这篇文章,也欢迎你分享你对这个自定义钩子的想法!此外,如果你喜欢我的文章,也可以在推特上关注我,或者请我喝杯咖啡,获取每日更新。
继续学习🙌
文章来源:https://dev.to/hey_yogini/useaxios-a-simple-custom-hook-for-calling-apis-using-axios-2dkj