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 组件中,我们只需调用一个get
API 来获取帖子列表。为此,我们使用了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