百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

React 中请求远程数据的四种方法(观战服务器数据请求失败解决方法)

zzlvtu 2024-09-04 23:00 5 浏览

作者:ConardLi

转发链接:https://mp.weixin.qq.com/s/DuzL0MEPMul00k55ulR7pA

React 是一个专注的组件库。因此,它对如何请求远程数据没有什么建议。如果要通过 HTTP 请求数据并将其发送到 Web API,可以考虑下面四种方法。

  • 内联写法
  • 集中管理
  • 自定义 Hook
  • react-query/swr

注意:在本文中,我将使用 fetch 进行 HTTP 调用,但是这些模式也适用于 Axios 之类的替代方法。另外,如果你使用的是 GraphQ L,还可以考虑使用 Apollo 之类的其他不错的选择。这篇文章假设你正在调用传统的 REST API。

方式1:内联

这是最简单,最直接的选择。在 React 组件中进行 HTTP 调用并处理响应。

fetch("/users").then(response => response.json());

看起来很简单。但是这个示例忽略了加载状态,错误处理,声明和设置相关状态等。在现实世界中, HTTP 调用看起来更像这样。

import React, { useState, useEffect } from "react";

export default function InlineDemo() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch(`${process.env.REACT_APP_API_BASE_URL}users`)
      .then(response => {
        if (response.ok) return response.json();
        throw response;
      })
      .then(json => {
        setUsers(json);
      })
      .catch(err => {
        console.error(err);
        setError(err);
      })
      .finally(() => {
        setLoading(false);
      });
  }, []);

  if (loading) return "Loading...";
  if (error) return "Oops!";
  return users[0].username;
}

对于一个简单的应用程序,只要发起几个请求,就可以正常工作。但是上面的状态声明和 useEffect 都是模版。如果我要进行许多 HTTP调用,我不想为每个调用重复和维护大约 20 行代码。内联调用让你的代码变得很丑。

看一下我们要解决的一些问题:

  • 声明加载状态
  • 声明错误状态
  • 将错误打印到控制台
  • 检查响应是否通过返回 200 response.ok
  • 如果响应正常,将响应转换为 json 并返回 promise
  • 如果响应不正确,抛出错误
  • 在 finally 中隐藏加载状态,以确保 Loading 即使发生错误也被隐藏
  • 声明一个空的依赖项数组,以便 useEffect 只运行一次

这只是一个简单的示例,它忽略了许多其他相关问题。

方式2:文件夹集中管理

如果我们在一个文件夹中处理所有 HTTP 调用会怎么样? 使用这种方法,我们创建了一个名为 services 的文件夹,并且把进行 HTTP 调用的函数都放进去。service 是最流行的术语,我在下面也讨论了很多好的替代名称,如 client 或 api。

要点是,所有的 HTTP 调用都是通过纯 JavaScript 函数处理的,存储在一个文件夹中。这是一个集中的 getUsers 函数:

export function getUsers() {
  return fetch(`${process.env.REACT_APP_API_BASE_URL}users`).then(response =>
    response.json()
  );
}

下面是对 getUsers 函数的调用:

import React, { useState, useEffect } from "react";
import { getUsers } from "./services/userService";

export default function CentralDemo() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  useEffect(() => {
    getUsers()
      .then(json => {
        setUsers(json);
        setLoading(false);
      })
      .catch(err => {
        console.error(err);
        setError(err);
      });
  }, []);

  if (loading) return "Loading...";
  if (error) return "Oops!";
  return users[0].username;
}

然而这并没有太简化请求调用。主要的好处是它可以强制一致地处理 HTTP 调用。其思想是这样的:当相关函数一起处理时,更容易一致地处理它们。如果 userService 文件夹中充满了进行 HTTP 调用的函数,那么我可以很容易地确保它们始终如一地这样做。此外,如果调用被复用,则很容易从这个集中位置调用它们。

然而,我们还可以做得更好。

方式3:自定义Hook

借助 React Hooks 的魔力,我们终于可以集中处理重复的逻辑。那么如何创建一个自定义 useFetch 钩子来简化我们的 HTTP 调用呢?

import { useState, useEffect, useRef } from "react";
// This custom hook centralizes and streamlines handling of HTTP calls
export default function useFetch(url, init) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const prevInit = useRef();
  const prevUrl = useRef();

  useEffect(() => {
  // Only refetch if url or init params change.
    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(response => {
        if (response.ok) return response.json();
        setError(response);
      })
      .then(data => setData(data))
      .catch(err => {
        console.error(err);
        setError(err);
      })
      .finally(() => setLoading(false));
  }, [init, url]);

  return { data, loading, error };
}

你的可能看起来不一样,但我发现这个基本的使用方法很有用。这个 Hook 极大地简化了所有调用。看看使用这个 Hook 需要多少代码 :

import React from "react";
import useFetch from "./useFetch";

export default function HookDemo() {
  const { data, loading, error } = useFetch("users");
  if (loading) return "Loading...";
  if (error) return "Oops!";
  return data[0].username;
}

对于许多应用程序,你只需要一个这样的自定义Hook。但是这个Hook已经很复杂了,并且它消除了许多问题。

但是还有很多我们没有考虑到的点:缓存?、如果客户端的连接不可靠,如何重新获取?你想在用户重新调整标签时重新获取新数据吗?如何消除重复查询?

你可以不断完善这个自定义Hook来完成所有这些操作。但是,您应该只需要方式4:

方式4:react-query/swr

使用 react-query或swr,可以为我们处理缓存、重试、重复查询等等。我不必维护自己的自定义Hook了。而且每个 HTTP 调用都需要很少的代码:

import React from "react";
import { getUsers } from "./services/userService";
import { useQuery } from "react-query";

export default function ReactQueryDemo() {
  const { data, isLoading, error } = useQuery("users", getUsers);
  if (isLoading) return "Loading...";
  if (error) return "Oops!";
  return data[0].username;
}

对于大多数应用程序来说,今天这是我的首选。这是完整的代码:https://codesandbox.io/s/4-ways-to-handle-restful-http-in-react-k3xug,你可以自己进行比较。

你是怎么处理 HTTP 调用的呢?欢迎和我讨论~

推荐React 学习相关文章

在React中实现和Vue一样舒适的keep-alive

我读完了React的API,并为新手送上了一些建议

基于 React 打造高自由度的 IDE 布局系统

推荐18个最佳React.js项目示例「值得收藏」

React.js 项目实践——创建个人作品集网页

细聊 React 是如何创建 vdom 和 fiber tree「实践」

深入浅出 React V16.4 生命周期的来龙去脉

在 React 中进行事件驱动的状态管理「实践」

一文带你搞懂React-native源码解析

常见的8个问题带你进阶 React

分析 React 组件的渲染性能「实践」

实践React Router v5:完整指南

前端必备的20种基本React工具「干货」

8个顶级React.js免费模板

推荐36种免费React模板和主题「干货」

「笔记」React Hooks 深入细品系列

这就是你日思夜想的 React 原生动态加载「值得收藏」

「干货满满」React Hooks 最佳实践

手把手教你如何实现一个React水印组件「实践」

「实践」React 中必会的 10 个概念

「干货」深入浅出React组件逻辑复用的那些事儿

手把手教你从Mixin深入到HOC再到Hook【React】

深入Facebook 官方React 状态管理器Recoil讲解

手把手教你实践搭建React组件库「超详细」

在 React 中自动复制文本到剪贴板「实践」

「干货满满」从零实现 react-redux

深入详解大佬用33行代码实现了React

让你的 React 组件性能跑得再快一点「实践」

React源码分析与实现(三):实践 DOM Diff

React源码分析与实现(一):组件的初始化与渲染「实践篇」

React源码分析与实现(二):状态、属性更新->setState「实践篇」

细说React 核心设计中的闪光点

手把手教你10个案例理解React hooks的渲染逻辑「实践」

React-Redux 100行代码简易版探究原理

手把手深入教你5个技巧编写更好的React代码【实践】

React 函数式组件性能优化知识点指南汇总

13个精选的React JS框架

深入浅出画图讲解React Diff原理【实践】

【React深入】React事件机制

Vue 3.0 Beta 和React 开发者分别杠上了

手把手深入Redux react-redux中间件设计及原理(上)【实践】

手把手深入Redux react-redux中间件设计及原理(下)【实践】

前端框架用vue还是react?清晰对比两者差异

为了学好 React Hooks, 我解析了 Vue Composition API

【React 高级进阶】探索 store 设计、从零实现 react-redux

写React Hooks前必读

深入浅出掌握React 与 React Native这两个框架

可靠React组件设计的7个准则之SRP

React Router v6 新特性及迁移指南

用React Hooks做一个搜索栏

你需要的 React + TypeScript 50 条规范和经验

手把手教你绕开React useEffect的陷阱

浅析 React / Vue 跨端渲染原理与实现

React 开发必须知道的 34 个技巧【近1W字】

三张图详细解说React组件的生命周期

手把手教你深入浅出实现Vue3 & React Hooks新UI Modal弹窗

手把手教你搭建一个React TS 项目模板

全平台(Vue/React/微信小程序)任意角度旋图片裁剪组件

40行代码把Vue3的响应式集成进React做状态管理

手把手教你深入浅出React 迷惑的问题点【完整版】

作者:ConardLi

转发链接:https://mp.weixin.qq.com/s/DuzL0MEPMul00k55ulR7pA

相关推荐

什么是DPDK?DPDK的原理及学习学习路线总结

一、什么是DPDK  对于用户来说,它可能是一个性能出色的包数据处理加速软件库;对于开发者来说,它可能是一个实践包处理新想法的创新工场;对于性能调优者来说,它可能又是一个绝佳的成果分享平台。 ...

每天进步一点:两分钟解决kvm下windows虚拟机鼠标不跟随

跟随昨天文章做测试的朋友们应该和我一样遇到了vnc连接windows鼠标不跟随的问题,经过一番查找有两种解决办法:1.编辑配置文件命令virshedittest或者直接vi/etc/libvir...

PC虚拟化主流:KVM、XEN、OpenVZ详解

目前,PC的虚拟化逐渐成为互联网发展的大趋势,我们知道,KVM、XEN、OpenVZ是虚拟化的三种方式,今天我们就来探讨这三种虚拟化的优势和劣势。1、pc虚拟化——KVMKVM是完整的硬件虚拟化,可在...

Windows上使用QEMU创建aarch64(ARM64)虚拟机

前言随着国产化的推进,现在采用ARM、MIPS的机器越来越多,作为开发、运维人员要调测软件总不能每种架构的机器都去买一台吧?主要像博主这样的穷B,实在也是承受不起。。需要的工具...

高度致敬Windows!开源优麒麟20.04 LTS发布:支持5年

优麒麟团队宣布,优麒麟(UbuntuKylin)开源操作系统20.04LTS正式版已经发布,代号FocalFossa,全球同步发布的还有Ubuntu20.04、Lubuntu20.04、Xub...

极空间虚拟机上线了,一学就会!小白保姆级使用教程

友情提示本文涉及内容较多,篇幅在4500字左右,为了对小白用户更加友好,图片示例多达60张。整个文章部分为三个阶段,准备-初探-实战。其中实战部分包含Windows系统,ikuai软路由系统,iSto...

Windows Subsystem for Linux现以应用形式上架Microsoft Store

微软今天宣布WindowsSubsystemforLinux(WSL)作为一款应用上架Windows11端的MicrosoftStore。也就是说,现在WSL以应用的方式通过...

Windows Server 2019 Core 虚拟机系统镜像制作

WindowsServer2019Core简介WindowsServer2019是微软于2018年11月13日发布的新一代WindowsServer服务器操作系统,基于Win10180...

微软商店中的WSL预览版现已可用!Windows 11用户狂喜

...

在NAS上安装Win10,24小时待命的云电脑达成√

#头条创作挑战赛#引子...

免费开源虚拟机VirtualBox 7.0.12发布:修复TPM和黑屏问题

IT之家10月18日消息,甲骨文近日发布了VirtualBox7.0.12维护版本更新,重点修复此前版本中用户反馈和官方发现的BUG,改善了对LinuxKernel6.4/6.5...

KVM Cloud 虚拟机管理系统安装部署

KVMCloud介绍KVMCloud是一款基于KVM实现的适用于小微企业的虚拟机管理系统,支持如下功能:基于KVM的VM基础功能(创建、启动、停止、重装、webVNC等功能)使用NFS作为磁盘...

个人KVM 虚拟化学习笔记(kvm虚拟化管理平台)

一、KVM原理二、KVM基础功能2.1CPU2.2内存2.3存储2.4网络三、KVM高级功能...

kvm虚拟化之ESXi到KVM之v2v迁移(esxi虚拟机迁移到另一个esxi)

1.ESXi到KVM之v2v情况说明(1).配置任务列表:1)VMwareESXi虚拟平台下linux系统迁移到KVM虚拟平台。2)VMwareESXi虚拟平台下windows系统迁移到KVM虚拟平台...

unraid下虚拟机安装Windows(vmware安装unraid)

unraid下虚拟机安装Windows使用unraid也有一段时间了,主要是做数据备份,以及docker容器的安装测试,今天有空测试一下VMS虚拟机的使用,用在unraid上安装windows7操作系...