React中最优雅的异步请求

news2025/2/7 3:48:57

给大家分享在React19中使用use+Suspense处理异步请求为什么是被认为最优雅的解决方案

一. 传统方案

解决异步请求的方案中,我们要处理至少两个最基本的逻辑

  1. 正常的数据显示
  2. 数据加载的UI状态

例如:

export default function Index(){
  const [content, update] = useState({value: ''})
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    api().then(res => {
      setLoading(false)
      update(res)
    })
  }, []);
  
  if (loading) {
    return <Skeleton/>
  }
  
  return (
    <Message message={content.value}/>
  )
}

很明显,每个页面都这样干的话,会比较繁琐。因此,通常会通过自定义hook的方式封装请求逻辑简化每个页面的代码

function useFetch() {
  const [content, update] = useState({value: ''})
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    api().then(res => {
      setLoading(false)
      update(res)
    })
  }, []);
    
  return {content,loading}
}

这样,页面代码就变成了如下更简洁的形式

function index2() {
  const {content, loading} = useFetch()

  if(loading) {
    return <Skeleton/>
  }
  
  return (
    <Message message={content.value}/>
  )
}

✅ 常用的ahooks、useQuery等,都是这个封装思路

在UI层面,我们还可以做一层封装,把loading封装到UI组件逻辑中去。常见的使用方式可以是这样

function Index2() {
  const {content, loading} = useFetch()

  return (
    <Message
      message={content.value}
      loading={loading}
    />
  )
}

也可以参考antd中,Spin的使用方式

function Index2() {
  const {content, loading} = useFetch()

  return (
    <Spin tip="Loading...">
      <Message
        message={content.value}
      />
    </Spin>
  )
}

img

通过这样的两步优化让我们页面代码变得非常简洁。这也是日常使用最多的方式,开发效率也非常高。

但随着使用经验的增加,也处理了更多的场景,几乎绝大多数场景都能够平滑的应对,但这种方式依旧存在一些小小的痛点。

当在思考如何封装usefetch 时,首先会考虑清楚在众多场景之下,有哪些东西是变化量。变化的内容我们将其设计为参数传入

function useFetch(params) {
  
}

常见的变化量包括:入参不同请求方式不同返回类型不同部分场景需要初始的默认值部分场景的接口并不需要立即请求返回结果可能需要二次处理才能正常使用参数变化之后的处理逻辑不同…

当不同的东西开始变得越来越多,优雅也在逐渐消失…

✅ 当前这肯定有对应的成套架构解决方案,到那时对于普通开发者来说变得有点难度,需要更丰富的经验来支撑才能应对各种不同的场景。

二. React 19的新方案

React19提出了一个新的方式,让我们应对这些复杂场景变得更加简单。那就是use + promise + Suspense

首先会把数据存储在promise中。然后promise定义为state

const _api3 = (params) => {
  return new Promise(resolve => {
    resolve({ value: 'React does not preserve any state for renders that got suspended before they were able to mount for the first time. When the component has loaded, React will retry rendering the suspended tree from scratch.' })
  })
}
const [promise, setPromise] = useState(_api3)

如果有默认参数需要传入,只需要在执行 _api3 时传入参数即可

const promise = useState(() => _api3({value: 10}))

如果我们在点击时,需要修改参数并且重新请求接口,可以一样重新执行_api3即可

function clickHandler(){
  _api3({value: 20})
}

由于触发UI更新必须借助state的变化,因此每次将_api3 执行返回的promise存储在useState中,点击时,_api3的执行结果必定是新的promise对象,因此,代码更改为如下,即可触发UI的更新

function clickHandler(){
  setPromise(_api3({value: 20}))
}

然后,将promise传入到具体的UI组件中去,并使用 Suspense 包裹起来

export default function Index() {
  const [promise, setPromise] = useState(_api3)
  return (
    <Suspense fallback={<Skeleton />}>
      <Message promise={promise} />
    </Suspense>
  )
}

然后在 UI 组件内部,使用 use 获取 promise 中的数据即可

const Message = (props) => {
  const content = use(props.promise)
  return (
    <div className='flex border border-blue-100 p-4 rounded-md shadow'>
      ...
    </div>
  )
}

在这套解决方案之下,参数的多变性处理起来就变得非常容易,可以直接控制参数是否变化,也可以直接控制接口是否需要重新请求。

只需要按照需求,在响应实践中执行对应的逻辑就可以了,而不需要像上面那种方案一样,还要额外封装,否则代码会变得更乱

function clickHandler() {
setPromise(_api({value: 20}))
}

认真体会这段代码的优越性,可以非常自由的在不同的场景处理参数。例如,有的地方可能需要缓存上一次的参数,但是有的地方不需要。那么需要缓存的场景,可以随便单独缓存即可。

也不用受限于参数的变化是否会引发接口的重新请求,这里参数的变化与接口的执行被解耦开,直接由我们开发时控制

三. 总结

很显然,react19 中提到的解决异步逻辑的方案,是目前为止,被认为是最优雅的方案。这种方案不需要我们再进一步二次封装,就能够轻松应对各种复杂的场景。这必将成为未来开发的主流方案。

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

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

相关文章

基于Bregman的交替方向乘子法

目录标题 ADMM方法简介Bregman散度Bregman ADMM的原理主要优势代码示例&#xff1a;各个符号的解释&#xff1a;**梯度的几何含义**&#xff1a;具体数学公式&#xff1a;**应用示例**&#xff1a;**ADMM的标准形式&#xff1a;****ADMM中的变量角色&#xff1a;****ADMM中的更…

`we_chat_union_id IS NOT NULL` 和 `we_chat_union_id != ‘‘` 这两个条件之间的区别

文章目录 1、什么是空字符串&#xff1f;2、两个引号之间加上空格 好的&#xff0c;我们来详细解释一下 we_chat_union_id IS NOT NULL 和 we_chat_union_id ! 这两个条件之间的区别&#xff0c;以及它们在 SQL 查询中的作用&#xff1a; 1. we_chat_union_id IS NOT NULL 含…

随机变量是一个函数-如何理解

文章目录 一. 随机变量二. 随机变量是一个函数-栗子(一对一)1. 掷骰子的随机变量2. 掷骰子的随机变量&#xff08;求点数平方&#xff09;3. 抛硬币的随机变量4. 学生考试得分的随机变量 三. 随机变量是一个函数-理解(多对一) 一. 随机变量 随机变量就是定义在样本空间上的函数…

jwt在express中token的加密解密实现方法

在我们前面学习了 JWT认证机制在Node.js中的详细阐述 之后&#xff0c;今天来详细学习一下token是如何生成的&#xff0c;secret密钥的加密解密过程是怎么样的。 安装依赖 express&#xff1a;用于创建服务器jsonwebtoken&#xff1a;用于生成和验证JWTbody-parser&#xff1…

大厂开发规范-如何规范的提交Git

多人协作开发提交代码通常是遵循约定式提交规范&#xff0c;如果严格安照约定式提交规范&#xff0c; 手动进行代码提交的话&#xff0c;那么是一件非常痛苦的事情&#xff0c;但是 Git 提交规范的处理又势在必行&#xff0c;那么怎么办呢&#xff1f; 经过了很多人的冥思苦想…

企业安装加密软件有什么好处?

加密软件为企业的安全提供了很多便利&#xff0c;从以下几点我们看看比较重要的几个优点&#xff1a; 1、数据保护&#xff1a;企业通常拥有大量的商业机密、客户数据、技术文档等敏感信息。加密软件可以对这些信息进行加密处理&#xff0c;防止未经授权的人员访问。即使数据被…

【ANGULAR网站开发】初始环境搭建

1. 初始化angular项目 1.1 创建angular项目 需要安装npm和nodejs&#xff0c;这边不在重新安装 直接安装最新版本的angular npm install -g angular/cli安装指定大版本的angular npm install -g angular/cli181.2 启动angular 使用idea启动 控制台启动 ng serve启动成功…

Python 屏幕取色工具

Python 屏幕取色工具 1.简介&#xff1a; 屏幕取色小工具‌是一种实用的软件工具&#xff0c;主要用于从屏幕上精确获取颜色值&#xff0c;非常适合设计、编程等需要精确配色的领域。这类工具通常能够从屏幕上任何区域精确提取颜色值&#xff0c;支持在整数值、RGB值、BGR值之…

宏集eX710物联网工控屏在石油开采机械中的应用与优势

案例概况 客户&#xff1a;天津某石油机械公司 应用产品&#xff1a;宏集eX710物联网工控屏 应用场景&#xff1a;钻井平台设备控制系统 一、应用背景 石油开采和生产过程复杂&#xff0c;涵盖钻井平台、采油设备、压缩机、分离器、管道输送系统等多种机械设备。这些设备通…

实验室服务器Ubuntu安装使用全流程

一、制作U盘启动盘 工具&#xff1a; 一个32G以上的U盘Rufuse镜像烧录软件下载&#xff1a;https://cn.ultraiso.net/xiazai.htmlRufus - 轻松创建 USB 启动盘https://cn.ultraiso.net/xiazai.htmlUbuntu系统镜像&#xff1a;https://ubuntu.com/download/alternative-downlo…

2-198基于Matlab-GUI的运动物体追击问题

基于Matlab-GUI的运动物体追击问题&#xff0c;定义目标航速、航线方向、鱼雷速度&#xff0c;并设置目标和鱼雷初始位置&#xff0c;根据航速和航向优化鱼雷路径&#xff0c;实现精准打击。程序已调通&#xff0c;可直接运行。 2-198基于Matlab-GUI的运动物体追击问题

实验五 时序逻辑电路部件实验

一、实验目的 熟悉常用的时序逻辑电路功能部件&#xff0c;掌握计数器、了解寄存器的功能。 二、实验所用器件和仪表 1、双 D触发器 74LS74 2片 2、74LS162 1片 3、74194 1片 4、LH-D4实验仪 1台 1.双…

UnityURP 自定义PostProcess之深度图应用

UnityURP 自定义PostProcess之深度图 前言项目Shader代码获取深度图ASE连线获取深度图 前言 在Unity URP中利用深度图可以实现以下两种简单的效果&#xff0c;其他设置参考 UnityURP 自定义PostProcess 项目 Shader代码获取深度图 Shader "CustomPost/URPScreenTintSha…

PlasmidFinder:质粒复制子的鉴定和分型

质粒&#xff08;Plasmid&#xff09;是一种细菌染色体外的线性或环状DNA分子&#xff0c;也是一种重要的遗传元素&#xff0c;它们具有自主复制能力&#xff0c;可以在细菌之间传播&#xff0c;并携带多种重要的基因(如耐药基因与毒力基因等)功能。根据质粒传播的特性&#xf…

mongodb(6.0.15)安装注意事项,重装系统后数据恢复

window10系统 上周重装了系统&#xff0c;环境变量之类的都没有了。现在要恢复。 我电脑里之前的安装包没有删除&#xff08;虽然之前也没在C盘安装&#xff0c;但是找不到了&#xff0c;所以需要重新下载安装&#xff09;&#xff0c;长下图这样。这个不是最新版本&#xff0…

【AI学习】DeepSeek-V3 技术报告学习:总体架构

翻了一下DeepSeek-V3 技术报告学习&#xff0c;太长&#xff0c;只是大概翻了一下&#xff0c;其中Multi-Token Prediction的技术就很亮眼。 摘要 本文介绍了DeepSeek-V3&#xff0c;这是一个拥有671B总参数的强大混合专家&#xff08;MoE&#xff09;语言模型&#xff0c;每…

b站ip属地评论和主页不一样怎么回事

在浏览B站时&#xff0c;细心的用户可能会发现一个有趣的现象&#xff1a;某些用户的评论IP属地与主页显示的IP属地并不一致。这种差异引发了用户的好奇和猜测&#xff0c;究竟是什么原因导致了这种情况的发生呢&#xff1f;本文将对此进行深入解析&#xff0c;帮助大家揭开这一…

Java中三大构建工具的发展历程(Ant、Maven和Gradle)

&#x1f438; 背景 我们要写一个Java程序&#xff0c;一般的步骤是编译&#xff0c;测试&#xff0c;打包。 这个构建的过程&#xff0c;如果文件比较少&#xff0c;我们可以手动使用java, javac,jar命令去做这些事情。但当工程越来越大&#xff0c;文件越来越多&#xff0c…

Wend看源码-Java-Map学习

摘要 在当今的编程世界中&#xff0c;深入了解各类数据类型对于开发者而言至关重要。本篇聚焦于 JDK 21 版本下&#xff0c;Java.util 包所提供的 Map 类型。Map 作为一种关键的数据结构&#xff0c;能够以键值对的形式高效存储和检索数据&#xff0c;广泛应用于众多领域。 本文…

uniapp开发微信小程序实现获取“我的位置”

1. 创建GetLocation项目 使用HBuilder X创建一个项目GetLocation,使用Vue3。 2. 在腾讯地图开放平台中创建应用 要获取位置,在小程序中需要使用腾讯地图或是高德地图。下面以腾讯地图为例。 (1)打开腾讯地图开放平台官方网址:腾讯位置服务 - 立足生态,连接未来 (2)注册…