在 React 中获取数据的6种方法

一、前言

数据获取是任何 react 应用程序的核心方面。对于 React 开发人员来说,了解不同的数据获取方法以及哪些用例最适合他们很重要。

但首先,让我们了解 JavaScript Promises。

简而言之,promise 是一个 JavaScript 对象,它将在未来的某个时间产生一个值。这通常适用于异步操作(例如数据获取)。

Promises具有三种状态:

  • Pending:承诺仍在进行中的地方
  • Fulfilled:承诺成功解决并返回值的地方
  • Rejected:承诺因错误而失败

如果一个promise被Fulfilled或Rejected,它就被解决了。Promise 有不同的方法来根据结果做不同的事情。下一节将更详细地讨论这些方法。

二、使用 Promise 方法获取 api

Fetch API 提供了一个全局的 fetch() 方法,使开发人员能够以直接的方式获取数据。在 fetch() 之前,传统方法是使用 XMLHttpRequest()。(本文不涉及此方法,因为 fetch() 已被更强大、更灵活的功能集所取代。)

fetch() 方法接受一个参数,即要请求的 URL,并返回一个promise。第二个可选参数options 是一个属性数组。fetch() 的返回值可以是 JSON 或 XML(对象数组或单个对象)。如果没有选项参数,fetch() 将始终发出 GET 请求。

第一种方法是您通常会在简单的数据获取用例中看到的方法,并且通常是浏览 API 文档时的第一个结果。

如前所述,我们从返回狗的随机图像的 API 获取数据,并将该图像呈现在屏幕上。在发出请求之前,我们将代码包装在一个带有空依赖项数组的 useEffecthook 中,以便 fetch() 方法仅在组件最初安装时运行。

useEffect(() => {fetch(URL)// syntax for handling promises.then((res) => {// check to see if response is okayif (res.ok) {// if okay, take JSON and parse to JavaScript objectreturn res.json();}throw res;})//  .json() returns a promise as well.then((data) => {console.log(data);// setting response as the data statesetData(data);})// if res is not okay the res is thrown here for error.catch((err) => {console.error(`Error: ${err}`);// setting the error statesetError(err);})//  regardless if promise resolves successfully or not we remove loading state.finally(() => {setLoading ( false );});}, []);

在上例中,我们调用该方法并传入 API 端点的 URL。在这个方法中,我们使用 promise 对象的方法(回想一下返回一个 promise)。

我们使用这个方法并传入一个回调函数来检查响应是否正常。如果响应正常,我们将获取返回的 JSON 数据并使用该方法将其解析为 JavaScript 对象。如果响应不正常,我们就会报错。

由于 .json() 方法也返回一个承诺,我们可以链接另一个 .then() 并传递一个函数来设置数据的状态,然后在组件的其他地方使用。在我们的示例中,外部 API 返回一个具有 url 属性的对象(它将用作 srcour 图像)。

继续通过链,下一部分是 .catch() 以安排在承诺被拒绝时调用的函数。这也返回另一个承诺,然后我们可以链接 .finally() 无论承诺是否已解决(解决或拒绝),它都会被调用。

这种 .finally() 方法使我们能够避免在 .then() 和 .catch() 中重复代码,使其成为我们示例中删除加载状态的好地方。

三、带有 Promise 方法的库 Axios

Axios 是一个流行的 HTTP 客户端库,用于高效的数据获取。它可以通过 npm 或其他包管理器轻松安装到 React 应用程序中。使用 Axios 是 Fetch API 的替代方法,如果您不介意安装外部库,它有一些优势。

第二个示例将非常接近第一个示例的代码,使用相同的 promise 方法来处理 promise 状态和响应。

在 fetch() 将 Axios 库导入我们的组件之后,我们可以使用 axios.get() 一种可以将 URL 传递到我们的外部 API 端点的方法。

这将返回一个 Promise,因此我们可以采用与 Promise 方法链接相同的方法。

useEffect(() => {axios.get(URL)// syntax for handling promises.then((res) => {console.log(res.data);// axios converts json to object for us (shortens our code)setData(res.data);})// axios takes care of error handling for us instead of checking manually.catch((err) => {console.error(`Error: ${err}`);// setting the error statesetError(err);})//  regardless if promise resolves successfully or not we remove loading state.finally(() => {setLoading ( false );});}, []);

Fetch API 的代码与此 Axios 方法之间的明显区别在于,使用 Axios 我们只需要一个,因为 Axios 为我们将 .then()JSON 转换为 JavaScript 对象(缩短了我们的代码)。

另外,我们不再写条件来手动抛出错误,因为axios会为你抛出400和500范围的错误(再次缩短我们的代码)。

四、异步函数(async/await)

在此示例中,我们将放弃在前两个示例中使用的承诺链,而是引入一种更现代的方法来编写异步的、基于承诺的代码。

这种方法可以与您选择的任何抓取机制一起使用,但对于本示例,我们将坚持使用 Axios 库。

第三个示例与前一个示例类似的方式设置组件,方法是导入 Axios 库,然后使用一个空的 dependencies 数组包装用于在 useEffecta 中获取数据的代码。

在 useEffect 中,我们使用关键字 async 创建一个异步函数,然后在该函数中我们有三个独立的部分 - try、catch 和 finally。

这种 try/catch 方法用于处理 JavaScript 中的错误。try块内的代码首先被执行,如果抛出任何错误,它们将被“捕获”在块中,catch并执行内部代码。

最后,finallyblock 将始终在流通过 try/catch 之后执行。

useEffect(() => {// create async function b/c cannot use async in useEffect arg cbconst fetchData = async () => {//   with async/await use the try catch block syntax for handlingtry {// using await to make async code look sync and shorten const res = await axios.get(URL);setData(res.data);} catch (err) {console.error(`Error: ${err}`);// setting the error statesetError(err);} finally {setLoading ( false );}};fetchData ();}, []);

在此示例中,try 块创建了一个名为 res(response 的缩写)的变量,该变量使用 async 关键字。这允许代码看起来同步(更短,更容易在眼睛上)。

在此示例中,axios.get(URL) 正在“等待”直到它稳定下来。如果承诺得到履行,那么我们将数据设置为状态。如果承诺被拒绝(抛出错误),它会进入 catch 块。

五、创建一个“useFetch”自定义 React Hook

第四种方法是创建我们自己的自定义 React 钩子,调用 useFetchit 可以在我们应用程序的不同组件中重复使用,并从每个组件中删除笨重的获取代码。

这个例子实际上只是采用第四个例子(使用 Axios 库和 async/await 的相同技术)并将该代码移动到它自己的自定义钩子中。

为此,我们创建了一个名为 useFetch.js 的函数。然后我们使用 Effect 将前面示例中的所有代码以及我们正在跟踪的不同状态添加到函数 useFetch 中。

最后,这个函数将返回一个包含每个状态的对象,然后在调用钩子的地方使用 useFetchaccessed。我们的 useFetchhook 还将接受一个参数,即 URL ,以允许更多的可重用性和向不同端点发出提取请求的可能性。

const useFetch = (url) => {const [data, setData] = useState(null);const [ loading , setLoading ] =  useState ( true );const [error, setError] = useState(null);useEffect(() => {// create async function b/c cannot use asyc in useEffect arg cbconst fetchData = async () => {//   with async/await use the try catch block syntax for handlingtry {// using await to make async code look sync and shortenconst res = await axios.get(url);setData(res.data);} catch (err) {console.error(`Error: ${err}`);// setting the error statesetError(err);} finally {setLoading ( false );}};fetchData ();}, []);return {data,loading,error,};
};

最后,我们将这个新的自定义钩子导入到将使用它的组件中,并像调用任何其他 React 钩子一样调用它。如您所见,这极大地提高了代码的可读性并缩短了我们的组件。

这种方法的最后一点是您还可以安装外部库而不是创建您自己的自定义挂钩。一个流行的库 react-fetch-hook 与我们刚刚构建的钩子具有非常相似的功能。

六、React 查询库

在 React 中获取数据的最现代和最强大的方法之一是使用 React Query 库。除了简单的数据获取之外,它还有许多功能,但是对于这个例子,我们将学习如何从同一个示例外部 API 中简单地获取数据。

安装和导入后,React Query 提供了许多自定义挂钩,可以以非常干净的方式在我们的组件中重复使用。

在此示例中,我们从中导入 QueryClient,然后使用提供程序包装我们的应用程序,并将 QueryClientProvider 实例作为属性传递给包装器。

这使我们能够在我们的应用程序中使用该库。

为了发出这个简单的 GET 请求,我们导入并使用了 useQueryhooks。与前面使用自定义挂钩的示例不同,我们传入了两个参数。

第一个必需参数是 queryKey ,用作此特定查询的参考键。

第二个必需参数是 queryFn ,它是查询将用于请求数据的函数。

我们将使用此查询函数,然后使用 Fetch API 和 promise 方法语法进行初始提取,而不是像我们之前的自定义挂钩示例中那样只传递一个简单的 URL。(这个钩子有许多其他可选参数。)

const { isLoading, error, data } = useQuery("dogData", () => fetch(URL).then((res) => res.json()));

isLoading 从这里开始,React Query 将在幕后完成所有额外的工作,在这种情况下,我们可以从这个钩子调用 destructure 、 error 和 use data in our application,尽管我们也可以访问许多其他值。

在比我们当前的 Dog Image API 示例更大的示例中,使用 React Query 的力量和优势是显而易见的。需要提及的一些附加功能包括:缓存、在后台更新“陈旧”数据以及其他与性能相关的优势。

七、Redux 工具包 RTK 查询

本文最后一种方法是使用Redux Toolkit的RTK Query进行数据采集。应用程序使用 Redux 进行状态管理是很常见的。

如果您的公司或您当前的副项目目前正在使用 Redux,一个不错的选择是使用 RTK 查询来获取数据,因为它提供了与 React 查询类似的简单性和优势。

要在存储 Redux 代码的任何地方开始使用 RTK 查询,请创建一个 rtkQueryService.js 文件来设置数据获取。

创建后,您将服务添加到您的 Redux 商店,假设您已经在使用 Redux,您将已经拥有一个包含您的应用程序的 <Provider>store 组件。

从这里开始,它与使用带有 React Query 方法的自定义钩子非常相似,您导入然后使用查询钩子并解构数据,错误然后是 Loading 可以在您的组件中使用。

const { data, error, isLoading } = useGetDogQuery();

如您所见,Redux 有很多设置,因此这可能不是我们用例的最佳方法,但如果您已经在 React 应用程序中使用 Redux 并且想要一种简单而现代的获取数据的方式,RTK 查询 可能很棒很有价值,这也提供了缓存等好处。

最后的想法

如果你已经看到了这里,那么恭喜你!这篇文章的目的就是为那些学习 React 的人介绍一些不同的数据获取方法。

在这篇文章中,我介绍了6种方法,希望这6种方法对你有用,也希望你能从中学习到一些新东西。

此外,还有其他当前的数据获取方法未在此文章中提及,我相信随着 React 生态系统的发展,其他方法将会出现。也就是说,我相信本文为理解该领域提供了坚实的基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/41342.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

排序+运算>直接运算的效率的原因分析

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

ADIS16470和ADIS16500从到手到读出完整数据,附例程

由于保密原因&#xff0c;不能上传我这边的代码&#xff0c;我所用的开发环境是IAR&#xff0c; 下边转载别的博主的文章&#xff0c;他用的是MDK 下文的博主给了你一个很好的思路&#xff0c;特此提出表扬 最下方是我做的一些手册批注&#xff0c;方便大家了解这个东西 原文链…

如何利用 ChatGPT 进行自动数据清理和预处理

推荐&#xff1a;使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 ChatGPT 已经成为一把可用于多种应用的瑞士军刀&#xff0c;并且有大量的空间将 ChatGPT 集成到数据科学工作流程中。 如果您曾经在真实数据集上训练过机器学习模型&#xff0c;您就会知道数据清理和预…

novnc 和 vnc server 如何实现通信?原理?

参考&#xff1a;https://www.codenong.com/js0f3b351a156c/

随机微分方程

应用随机过程|第7章 随机微分方程 见知乎&#xff1a;https://zhuanlan.zhihu.com/p/348366892?utm_sourceqq&utm_mediumsocial&utm_oi1315073218793488384

复习3-5天【80天学习完《深入理解计算机系统》】第七天

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

Linux与bash(基础内容一)

一、常见的linux命令&#xff1a; 1、文件&#xff1a; &#xff08;1&#xff09;常见的文件命令&#xff1a; &#xff08;2&#xff09;文件属性&#xff1a; &#xff08;3&#xff09;修改文件属性&#xff1a; 查看文件的属性&#xff1a; ls -l 查看文件的属性 ls …

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows 摘要当前的检测sota模型网络架构swin Transformer和Vision Transformer的不同之处整体架构Patch Partition结构Linear Embedding结构Swin Transformer Block结构 Patch MergingW-MSAMSA模块计算量W-M…

Genoss GPT简介:使用 Genoss 模型网关实现多个LLM模型的快速切换与集成

一、前言 生成式人工智能领域的发展继续加速&#xff0c;大型语言模型 (LLM) 的用途范围不断扩大。这些用途跨越不同的领域&#xff0c;包括个人助理、文档检索以及图像和文本生成。ChatGPT 等突破性应用程序为公司进入该领域并开始使用这项技术进行构建铺平了道路。 大公司正…

如何发布自己的小程序

小程序的基础内容组件 text&#xff1a; 文本支持长按选中的效果 <text selectable>151535313511</text> rich-text: 把HTML字符串渲染为对应的UI <rich-text nodes"<h1 stylecolor:red;>123</h1>"></rich-text> 小程序的…

MySql过滤重复数据

假设模型表是: 1. 根据单字段过滤: SELECT user_name, COUNT(*) as count FROM sys_user GROUP BY user_name HAVING count > 1;结果: 2. 根据多个字段查询重复数据 SELECT user_name, email, COUNT(*) as count FROM sys_user GROUP BY user_name, email HAVING count…

[centos]设置主机名

1、设置 hostnamectl set-hostname 名字 2、查看是否生效 hostnamectl status 3、打开一个新链接就可以了

[python] 使用Jieba工具中文分词及文本聚类概念

前面讲述了很多关于Python爬取本体Ontology、消息盒InfoBox、虎扑图片等例子&#xff0c;同时讲述了VSM向量空间模型的应用。但是由于InfoBox没有前后文和语义概念&#xff0c;所以效果不是很好&#xff0c;这篇文章主要是爬取百度5A景区摘要信息&#xff0c;再利用Jieba分词工…

hive--给表名和字段加注释

1.建表添加注释 CREATE EXTERNAL TABLE test(loc_province string comment 省份,loc_city string comment 城市,loc_district string comment 区,loc_street string comment 街道,)COMMENT 每日数据处理后的表 PARTITIONED BY (par_dt string) ROW FORMAT SERDEorg.apache.had…

71 # 协商缓存的配置:通过内容

对比&#xff08;协商&#xff09;缓存 比较一下再去决定是用缓存还是重新获取数据&#xff0c;这样会减少网络请求&#xff0c;提高性能。 对比缓存的工作原理 客户端第一次请求服务器的时候&#xff0c;服务器会把数据进行缓存&#xff0c;同时会生成一个缓存标识符&#…

Transformer是什么,Transformer应用

目录 Transformer应用 Transformer是什么 Transformer应用:循环神经网络 语言翻译:注重语句前后顺序 RNN看中单个特征; CNN:看中特征之间时序性 模型关注不同位置的能力 Transformer是什么 Transformer是一个利用注意力机制来提高模型训练速度的模型。关于注意力机…

whisper语音识别部署及WER评价

1.whisper部署 详细过程可以参照&#xff1a;&#x1f3e0; 创建项目文件夹 mkdir whisper cd whisper conda创建虚拟环境 conda create -n py310 python3.10 -c conda-forge -y 安装pytorch pip install --pre torch torchvision torchaudio --extra-index-url 下载whisper p…

智慧工地云平台源码——塔机监控系统

智慧工地概念 智慧工地是一种崭新的工程全生命周期管理理念&#xff0c;是指运用信息化手段&#xff0c;通过对工程项目进行精确设计和施工模拟&#xff0c;围绕施工过程管理&#xff0c;建立互联协同、智能生产、科学管理的施工项目信息化生态圈&#xff0c;并将此数据在虚拟…

鸽王-稚晖君,“远征”A1启程

看到这篇文章的人&#xff0c;想必对野生钢铁侠-稚晖君&#xff0c;都有所了解。作为华为的天才少年&#xff0c;获得了很多的荣誉&#xff0c;作为B站有名的鸽王&#xff0c;在沉浮一段时间后终于要带着新的东西和大家见面了。动态-哔哩哔哩https://b23.tv/Jv7tIjg 众所周知&a…

网络通信原理TCP字段解析(第四十七课)

字段含义Source Port(源端口号)源端口,标识哪