当前位置:首页 > 科技  > 软件

一个巧妙设计,解锁 React19 初始化接口优秀实践,彻底摒弃 useEffect

来源: 责编: 时间:2024-06-12 17:32:48 77观看
导读在以往的开发思路中,初始化接口需要借助 useEffect。和最初的 class 语法相比,借助 useEffect 实现接口请求是一次代码简洁度的大幅度提升。function Messages() { var [data, setData] = useState() useEffect(() =>

WUh28资讯网——每日最新资讯28at.com

在以往的开发思路中,初始化接口需要借助 useEffect。和最初的 class 语法相比,借助 useEffect 实现接口请求是一次代码简洁度的大幅度提升。WUh28资讯网——每日最新资讯28at.com

function Messages() {  var [data, setData] = useState()  useEffect(() => {    api().then(res => {      setData(res.data)    })  }, [])  ...}

在 React 19 中,由于 use() hook 的出现,让我们有机会不借助 useEffect 就可以简单实现初始化。代码简洁度将会进一步提升。我们来回顾一下如何做。WUh28资讯网——每日最新资讯28at.com

先定义好一个 api 请求的函数。此时我们要重新注意 getMessage 执行,返回的是一个 promise。WUh28资讯网——每日最新资讯28at.com

const getMessage = async () => {  const res = await fetch('https://api.chucknorris.io/jokes/random')  return res.json()}

有了这个 api 之后,我们可以直接在父组件中调用该方法。WUh28资讯网——每日最新资讯28at.com

var promise = getMessage()

由于 getMessage 执行返回的依然是一个 promise,因此我们可以将这个 promise 传递给子组件。在子组件中使用 use 读取 promise 中的值。WUh28资讯网——每日最新资讯28at.com

// 被 Suspense 包裹的子组件const res = use(api)

只需要这两行代码,就可以非常简单的在组件中请求接口并初始化页面了。但是我们在前面的文章中有提到过,一个新的架构思路如何不能解决所有问题,那么这个架构思路就是不成功的,我们便不能称之为架构思维。WUh28资讯网——每日最新资讯28at.com

在前面的案例中,我们确实遇到了一些更复杂的情况,并且采用了一些不太理想的方式来解决。我们来回顾一下。WUh28资讯网——每日最新资讯28at.com

一个常见的需求场景就是,我们不仅要在初始化时请求接口,并且还要在后续的交互中「点击更新、重置、下拉刷新等」请求同样的接口。此时我们刚才非常简洁的写法就变得不再适用了。一个交互案例如下图所示:WUh28资讯网——每日最新资讯28at.com

WUh28资讯网——每日最新资讯28at.com

在前面的案例中,我们巧妙的将 promise 作为状态存储在 state 中,勉强解决了这个问题。WUh28资讯网——每日最新资讯28at.com

var [promise, setPromise] = useState(getMessage())

交互事件触发时,只需要执行 getMessage() 并用此结果更新 promise 的值,组件就会重新请求。WUh28资讯网——每日最新资讯28at.com

function __clickHandler() {  setPromise(getMessage())}

这种用法非常高级,因为在我们的固有思维中,state 中存储的都是可以触发更新的状态/数据,而这种用法实际上是在数据外套了一层 promise,我们将数据存储在 promise 中。在保持了代码简洁性的同时,没有新增状态并且最终解决了问题。WUh28资讯网——每日最新资讯28at.com

但是,这并不是最理想的解决方案。因为这种写法,当组件由于各种原因需要重新请求时,getMessage() 会冗余执行,它的执行就会请求接口,因此这种写法会造成大量的冗余请求。WUh28资讯网——每日最新资讯28at.com

为了解决这个问题,我们在前面一章的案例中,使用了一种并不简洁的方案,来防止 getMessage() 的冗余执行。这个思路的核心是利用 useEffect 的执行,来记录组件已经完成初始化,然后在函数组件后续的执行中,就可以阻止 getMessage 的执行。WUh28资讯网——每日最新资讯28at.com

var r = useRef(false)var api = r.current ? null : getMessage()const [promise, setPromise] = useState(api)const [current, setCurrent] = useState(0)useEffect(() => {  r.current = true}, [])

绕来绕去,useEffect 又回来了。很显然,这违背了我们的初衷。虽然解决了问题,但是看上去非常的别扭。WUh28资讯网——每日最新资讯28at.com

那么有没有更简单直接的、符合 React 19 开发思维的、彻底摒弃 useEffect 的解决方案呢?当然有。WUh28资讯网——每日最新资讯28at.com

我们需要巧妙的利用 React 语法的机制,来达到目的。WUh28资讯网——每日最新资讯28at.com

我们仔细观察一下 getMessage 的封装。实际上,当我们调用该方法时,请求就已经发生了。WUh28资讯网——每日最新资讯28at.com

const getMessage = async () => {  const res = await fetch('https://api.chucknorris.io/jokes/random')  return res.json()}

所以,当父组件重复执行时,getMessage() 也会重复执行,请求自然也会重复发送。因此,一个比较自然的思考,就是想办法让 getMessage 只执行一次。WUh28资讯网——每日最新资讯28at.com

调整的方式非常简单,如下所示WUh28资讯网——每日最新资讯28at.com

+ var [, setPromise] = useState(getMessage)- var [, setPromise] = useState(getMessage())

这里就是我们这篇文章要重点给大家介绍的非常巧妙的地方。我们借助了 useState 的另外一种方式来初始化。来观察一下官方文档的案例。WUh28资讯网——每日最新资讯28at.com

WUh28资讯网——每日最新资讯28at.com

const [todos, setTodos] = useState(() => createTodos());

注意看一下这段代码,他使用一个函数来初始化 todos,初始化之后,todos 的值,为 createTodos() 的执行结果。这种方式初始化的结果是,createTodos() 只会在组建首次创建时执行一次,后续组件再 re-render,就不再执行了。WUh28资讯网——每日最新资讯28at.com

又由于在函数式编程中,函数是一等公民,因此,上面的代码可以简化为。WUh28资讯网——每日最新资讯28at.com

const [todos, setTodos] = useState(createTodos);

所以此时,我们使用 useState(getMessage) 则是借用了这种语法思路,将我们的代码做到极简的方式给 state 赋值。他等价于。WUh28资讯网——每日最新资讯28at.com

var [] = useState(() => getMessage())// 两种写法的运行结果是一致的var [] = useState(getMessage)

交互事件触发时代码可以保持不变。WUh28资讯网——每日最新资讯28at.com

function __clickHandler() {  setPromise(getMessage())}

确实太帅了,一个非常小的调整,就解决了问题。WUh28资讯网——每日最新资讯28at.com

而这种小小的巧妙调整,结合我们把 promise 存储在 state 的巧思,几乎就可以宣告 useEffect 在异步请求的实现中,可以功成身退了。当你理解了这个细节,你就应该能完全感受到 react 19 的强大吸引力了。也因此,我对 React19 无比期待。WUh28资讯网——每日最新资讯28at.com

极简风格的代码表现如下:WUh28资讯网——每日最新资讯28at.com

WUh28资讯网——每日最新资讯28at.com

不得不说,评论区里有高人。在上一篇文章中就有人已经提到过这种调整方向。WUh28资讯网——每日最新资讯28at.com

WUh28资讯网——每日最新资讯28at.com

WUh28资讯网——每日最新资讯28at.com

有的时候,我们需要在请求时传入参数,那么写法简单调整如下:WUh28资讯网——每日最新资讯28at.com

var [] = useState(() => getMessage(params))function __clickHandler() {  setPromise(getMessage(params))}...

最后总结一下,我们注意看下面两种写法:WUh28资讯网——每日最新资讯28at.com

// 写法一:const _api2 = new Promise((resolve) => {  resolve({ value: 29 })})

写法二:WUh28资讯网——每日最新资讯28at.com

function fetchMessage() {  return new Promise((resolve) => {    setTimeout(resolve, 1000, '***')  })}

当我们要直接用 use 从 promise 中获取数据时,必须是写法一这种方式。当我们把 promise 保存在 useState 上时,写法一与写法二都可以。WUh28资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-93373-0.html一个巧妙设计,解锁 React19 初始化接口优秀实践,彻底摒弃 useEffect

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 提高能效,用Rust写代码

下一篇: 前端性能指标,一网打尽!

标签:
  • 热门焦点
  • 对标苹果的灵动岛 华为带来实况窗功能

    对标苹果的灵动岛 华为带来实况窗功能

    继苹果的灵动岛之后,华为也在今天正式推出了“实况窗”功能。据今天鸿蒙OS 4.0的现场演示显示,华为的实况窗可以更高效的展现出实时通知,比如锁屏上就能看到外卖、打车、银行
  • 红魔电竞平板评测:大屏幕硬实力

    红魔电竞平板评测:大屏幕硬实力

    前言:三年的疫情因为要上网课的原因激活了平板市场,如今网课的时代已经过去,大家的生活都恢复到了正轨,这也就意味着,真正考验平板电脑生存的环境来了。也就是面对着这种残酷的
  • vivo TWS Air开箱体验:真轻 臻好听

    vivo TWS Air开箱体验:真轻 臻好听

    在vivo S15系列新机的发布会上,vivo的最新款真无线蓝牙耳机vivo TWS Air也一同发布,本次就这款耳机新品给大家带来一个简单的分享。外包装盒上,vivo TWS Air保持了vivo自家产
  • 7月安卓手机性能榜:红魔8S Pro再夺榜首

    7月安卓手机性能榜:红魔8S Pro再夺榜首

    7月份的手机市场风平浪静,除了红魔和努比亚带来了两款搭载骁龙8Gen2领先版处理器的新机之外,别的也想不到有什么新品了,这也正常,通常6月7月都是手机厂商修整的时间,进入8月份之
  • 六大权益!华为8月服务日开启:手机免费贴膜、维修免人工费

    六大权益!华为8月服务日开启:手机免费贴膜、维修免人工费

    8月5日消息,一年一度的华为开发者大会2023(Together)日前在松山湖拉开帷幕,与此同时,华为8月服务日也式开启,到店可享六大专属权益。华为用户可在华为商城Ap
  • 掘力计划第 20 期:Flutter 混合开发的混乱之治

    掘力计划第 20 期:Flutter 混合开发的混乱之治

    在掘力计划系列活动第20场,《Flutter 开发实战详解》作者,掘金优秀作者,Github GSY 系列目负责人恋猫的小郭分享了Flutter 混合开发的混乱之治。Flutter 基于自研的 Skia 引擎
  • 微信语音大揭秘:为什么禁止转发?

    微信语音大揭秘:为什么禁止转发?

    大家好,我是你们的小米。今天,我要和大家聊一个有趣的话题:为什么微信语音不可以转发?这是一个我们经常在日常使用中遇到的问题,也是一个让很多人好奇的问题。让我们一起来揭开这
  • 一文搞定Java NIO,以及各种奇葩流

    一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • 三星Galaxy Z Fold5今日亮相:厚度缩减但仍略显厚重

    三星Galaxy Z Fold5今日亮相:厚度缩减但仍略显厚重

    据官方此前宣布,三星将于7月26日也就是今天在韩国首尔举办Unpacked活动,届时将带来带来包括Galaxy Buds 3、Galaxy Watch 6、Galaxy Tab S9、Galaxy
Top
Baidu
map