请求远程数据的四种方法: 1、直接在React组件中进行HTTP调用,并处理响应; 2、创建一个文件夹,把所有进行HTTP调用的函数放进去,集中请求数据并处理响应; 3、自定义Hook来请求数据; 4.使用“react-query”或swr请求数据。
从“react”导入React,{useState,useEffect};
导出默认函数 InlineDemo() {
const [用户,setUsers] = useState([]);
const [正在加载,setLoading] = useState(true);
const [错误,setError] = useState(null);
使用效果(()=> {
fetch(`${process.env.REACT_APP_API_BASE_URL}用户`)
.then(响应=> {
if (response.ok) 返回response.json();
抛出响应;
})
.then(json => {
设置用户(json);
})
.catch(错误=> {
控制台.错误(错误);
设置错误(错误);
})
.finally(() => {
设置加载(假);
});
}, []);
如果(正在加载)返回“正在加载...”;
如果(错误)返回“哎呀!”;
返回用户[0].用户名;}
对于一个简单的应用程序,只需提出一些请求,它就应该可以正常工作。但上面的状态声明和useEffect
都是模板。如果我要进行多次 HTTP
调用,我不想为每个调用重复并维护大约 20 行代码。内联调用使您的代码看起来很丑陋。
看看我们正在尝试解决的一些问题:
状态加载状态
声明错误状态
将错误打印到控制台
检查响应是否通过,返回200 response.ok
如果响应正常,则将响应转换为json
并返回promise
如果响应不正确,则抛出错误
隐藏最后
中的加载状态,以确保即使发生错误也隐藏加载中
声明一个空的依赖数组,以便useEffect
只运行一次
这只是一个简单的例子,忽略了许多其他相关问题。
如果我们在一个文件夹中处理所有HTTP
调用会怎么样?使用这种方法,我们创建一个名为 services
的文件夹,并将所有进行 HTTP 调用的函数放入其中。 服务
是最流行的术语,我还在下面讨论了很多好的替代名称,例如client
或api
。
导出函数getUsers () {
返回 fetch(`${process.env.REACT_APP_API_BASE_URL}users`).then(response =>
响应.json()
);
}
以下是对getUsers
函数的调用:
从“react”导入 React, { useState, useEffect }; 从“./services/userService”导入{ getUsers }; 导出默认函数 CentralDemo() { const [用户,setUsers] = useState([]); const [正在加载,setLoading] = useState(true); const [错误,setError] = useState(null); 使用效果(()=> { 获取用户() .then(json => { 设置用户(json); 设置加载(假); }) .catch(错误=> { 控制台.错误(错误); 设置错误(错误); }); }, []); 如果(正在加载)返回“正在加载...”; 如果(错误)返回“哎呀!”; 返回用户[0].用户名; }
但这并没有过多简化请求调用。主要好处是它强制对 HTTP
调用进行一致处理。这个想法是这样的:当相关的函数一起处理时,更容易一致地处理它们。如果 userService
文件夹中充满了进行 HTTP
调用的函数,那么我可以轻松确保它们始终如一地执行。此外,如果重复使用调用,则可以轻松地从此集中位置调用它们。
但是,我们可以做得更好。
借助React Hooks
的魔力,我们终于可以专注于重复的逻辑了。那么,创建一个自定义 useFetch
挂钩来简化我们的 HTTP
调用怎么样?
从“react”导入 { useState, useEffect, useRef }; // 这个自定义挂钩集中并简化了 HTTP 调用的处理 导出默认函数 useFetch(url, init) { const [数据,setData] = useState(null); const [正在加载,setLoading] = useState(true); const [错误,setError] = useState(null); const prevInit = useRef(); const prevUrl = useRef(); 使用效果(()=> { // 仅当 url 或 init 参数更改时才重新获取。 if (prevUrl.current === url && prevInit.current === init) return; prevUrl.current = url; prevInit.current = init; fetch(process.env.REACT_APP_API_BASE_URL + url, init) .then(响应=> { if (response.ok) 返回response.json(); 设置错误(响应); }) .then(数据 => setData(数据)) .catch(错误=> { 控制台.错误(错误); 设置错误(错误); }) .finally(() => setLoading(false)); }, [init, url]); 返回{数据,加载,错误};}
您的可能看起来有所不同,但我发现这种基本用法很有帮助。这个 Hook 极大地简化了所有调用。看看使用这个 Hook
需要多少代码:
从“react”导入React; 从“./useFetch”导入useFetch; 导出默认函数 HookDemo() { const { 数据,加载,错误 } = useFetch("users"); 如果(正在加载)返回“正在加载...”; 如果(错误)返回“哎呀!”; 返回数据[0].用户名; }
对于许多应用程序,您只需要像这样的自定义Hook。但这个 Hook 已经很复杂了,它消除了很多问题。
但是还有很多点我们没有考虑到:缓存? 。如果客户端的连接不可靠,如何重新获取呢?当用户调整标签大小时,您想重新获取新数据吗?如何消除重复查询?
你可以继续完善这个自定义Hook来完成所有这些操作。然而,你应该只需要方法 4:
使用react-query或者swr
,它可以为我们处理缓存、重试、重复查询等。我不必维护自己的自定义 Hook。每个 HTTP
调用只需要很少的代码:
从“react”导入React; 从“./services/userService”导入{ getUsers }; 从“react-query”导入{useQuery}; 导出默认函数 ReactQueryDemo() { const { data, isLoading, error } = useQuery("users", getUsers); if (isLoading) 返回“正在加载...”;如果(错误)返回“哎呀!”; 返回数据[0].用户名; }
这是我今天对于大多数应用程序的首选。完整代码如下:https://www.hack95.com/s/4-ways-to-handle-restful-http-in-react-k3xug
,大家可以自己对比一下。
推荐学习:《react视频教程》