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

喔!React19 中的 Hook 可以写在 If 条件判断中了。Use 实践:点击按钮更新数据

来源: 责编: 时间:2024-06-06 17:41:31 308观看
导读接下来,我们将会以大量的实践案例来展开 React 19 新 hook 的运用。本文模拟的实践案例为点击按钮更新数据。这在开发中是一个非常常见的场景。案例完成之后的最终演示效果图如下:我们直接用 React 19 新的开发方式来完

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

接下来,我们将会以大量的实践案例来展开 React 19 新 hook 的运用。zGj28资讯网——每日最新资讯28at.com

本文模拟的实践案例为点击按钮更新数据。这在开发中是一个非常常见的场景。zGj28资讯网——每日最新资讯28at.com

案例完成之后的最终演示效果图如下:zGj28资讯网——每日最新资讯28at.com

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

我们直接用 React 19 新的开发方式来完成这个需求。zGj28资讯网——每日最新资讯28at.com

一、基础实现

首先创建一个方法用于请求数据。zGj28资讯网——每日最新资讯28at.com

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

这里一个非常关键的地方就在于,当我们要更新的数据时,我们不再需要设计一个 loading 状态去记录数据是否正在发生请求行为,因为 Suspense 帮助我们解决了 Loading 组件的显示问题。zGj28资讯网——每日最新资讯28at.com

与此同时,use() 又帮助我们解决了数据获取的问题。那么问题就来了,这个就是,好像我们也不需要设计一个状态去存储数据。那么应该怎么办呢?zGj28资讯网——每日最新资讯28at.com

这里有一个非常巧妙的方式,就是把创建的 promise 作为状态值来触发组件的重新执行。每次点击,我们都需要创建新的 promisezGj28资讯网——每日最新资讯28at.com

代码如下:zGj28资讯网——每日最新资讯28at.com

// 记住这个初始值const [api, setApi] = useState(null)

这个时候,当我们点击事件执行时,则只需要执行如下代码去触发组件的更新。zGj28资讯网——每日最新资讯28at.com

function __clickToGetMessage() {  // 每次点击,都会创建新的 promise  setApi(getApi())}

getApi() 执行,新的请求会发生。他的执行结果,又返回了一个新的 promise。zGj28资讯网——每日最新资讯28at.com

因此,点击之后会创建的新 promise 值,api 此时就会作为状态更改触发组件的更新。zGj28资讯网——每日最新资讯28at.com

完整代码如下:zGj28资讯网——每日最新资讯28at.com

export default function Index() {  const [api, setApi] = useState(null)  function __clickToGetMessage() {    setApi(getApi())  }  return (    <div>      <div id='tips'>点击按钮获取一条新的数据</div>      <button onClick={__clickToGetMessage}>获取数据</button>      <div className="content">        <Suspense fallback={<div>loading...</div>}>          <Item api={api} />        </Suspense>      </div>    </div>  )}const Item = (props) => {  if (!props.api) {    return <div>nothing</div>  }  const joke = use(props.api)  return (    <div className='a_value'>{joke.value}</div>  )}

案例写完之后。我们基本上就能够实现最开始截图中的交互效果了。但是现别急,还没有完。我们还需要进一步分析一下这个案例。zGj28资讯网——每日最新资讯28at.com

二、案例分析

这里我们需要注意观察两个事情。zGj28资讯网——每日最新资讯28at.com

一个是观察当前组件更新,更上层的父组件是否发生了变化。我们可以在 App 组件中执行一次打印。zGj28资讯网——每日最新资讯28at.com

此时可以发现,当我们重新请求时,当前组件更新,但是上层组件并不会重新执行。zGj28资讯网——每日最新资讯28at.com

我们可以出得结论:更简洁的状态设计,有利于命中 React 默认的性能优化规则。zGj28资讯网——每日最新资讯28at.com

具体的规则请在 React 知命境合集中查看。zGj28资讯网——每日最新资讯28at.com

更简洁的状态设计,也是 React 19 所倡导的开发思路。zGj28资讯网——每日最新资讯28at.com

另外一个事情,是我们要特别特别注意观察子组件 Item 的实现。zGj28资讯网——每日最新资讯28at.com

首先因为我们初始化时,给 api 赋予的默认值是 null。zGj28资讯网——每日最新资讯28at.com

// 记住这个初始值const [api, setApi] = useState(null)

之后,我们就将 api 传给了子组件 Item。zGj28资讯网——每日最新资讯28at.com

<Item api={api} />

然后在 Item 组件的内部实现中,因为我们直接把 api 传给了 use,那么此时直接执行肯定会报错。zGj28资讯网——每日最新资讯28at.com

const joke = use(props.api)

要注意的是,我们刚才说,使用 Suspense 会捕获子组件的异常,但是不是捕获所有异常,它只能识别 promise 的异常。因此,这里的报错会直接影响到整个页面。zGj28资讯网——每日最新资讯28at.com

所以,为了处理好初始化时传入 api 值为 null,我在内部实现代码逻辑中,使用了 if 判断该条件,然后执行了一次 return。我试图让 use(null) 得不到执行的时机。zGj28资讯网——每日最新资讯28at.com

const Item = (props) => {  if (!props.api) {    console.log('初始化时,api == null')    return <div>nothing</div>  }  const joke = use(props.api)  return (    <div className='a_value'>{joke.value}</div>  )}

那么,我的意图是否能成功呢?zGj28资讯网——每日最新资讯28at.com

我们在 return 后面插入一个 console.log 来观察代码的执行情况,代码如下:zGj28资讯网——每日最新资讯28at.com

const Item = (props) => {  if (!props.api) {    console.log('初始化时,api == null')    return <div>nothing</div>  }    console.log('初始化时这里是否执行');  const joke = use(props.api)  return (    <div className='a_value'>{joke.value}</div>  )}

演示效果如下图所示:zGj28资讯网——每日最新资讯28at.com

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

我们发现,当我反复刷新页面,让初始化流程执行时,return 后面的代码并不会执行。zGj28资讯网——每日最新资讯28at.com

再然后,我们新增一点内容,比如在 return 后面使用一个 useEffect。zGj28资讯网——每日最新资讯28at.com

const Item = (props) => {  if (!props.api) {    console.log('初始化时,api == null')    return <div>nothing</div>  }  useEffect(() => {    console.log('xxx')  }, [])  console.log('初始化时这里是否执行')  const joke = use(props.api)  return (    <div className='a_value'>{joke.value}</div>  )}

然后演示再看看。我们发现 effect 也不会执行。然后我们还可以搞点好玩的。zGj28资讯网——每日最新资讯28at.com

Item 代码改造如下:zGj28资讯网——每日最新资讯28at.com

const Item = (props) => {  if (!props.api) {    const [count, setCount] = useState(0)    console.log('初始化时,api == null')    return <div onClick={() => setCount(count + 1)}>nothing, {count}</div>  }  console.log('初始化时这里是否执行')  const joke = use(props.api)  return (    <div className='a_value'>{joke.value}</div>  )}

注意看,我们在 if 条件判断中,单独创建了一个 useState,并在对应的元素上添加了一个让 count 递增的交互。zGj28资讯网——每日最新资讯28at.com

这段在之前版本的开发中一定会触发语法错误提示的代码。zGj28资讯网——每日最新资讯28at.com

最终也是能勉强运行,但是代码会疯狂报错。zGj28资讯网——每日最新资讯28at.com

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

然后,我继续一个骚操作,我在 if 中条件判断中,使用 useEffect,代码如下:zGj28资讯网——每日最新资讯28at.com

const Item = (props) => {  if (!props.api) {    useEffect(() => {      console.log('useEffect 在 if 中执行')    }, [])    return <div>nothing</div>  }  console.log('初始化时这里是否执行')  const joke = use(props.api)  return (    <div className='a_value'>{joke.value}</div>  )}

也能正常执行。观察一下演示效果:zGj28资讯网——每日最新资讯28at.com

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

结论:zGj28资讯网——每日最新资讯28at.com

很明显,react 19 的 hook 在底层发生了一些优化更新,我们可以不用非得把所有的 hook 都放在函数组件的最前面去执行了。zGj28资讯网——每日最新资讯28at.com

在 React 19 中,我们可以把 hook 放到 return 之后,也可以放到条件判断中去执行。zGj28资讯网——每日最新资讯28at.com

但是,我们一定要注意的是,并非表示我们可以随便乱写。当条件互斥时,状态之间如果存在不合理的耦合关系,依然不能正常执行。我们列举两个案例来观察这个事情。zGj28资讯网——每日最新资讯28at.com

第一个案例,我们依然在 if 中执行一个 useEffect,但是不同的是,我把在 if 之外的状态 counter 作为依赖项传入。zGj28资讯网——每日最新资讯28at.com

代码如下。zGj28资讯网——每日最新资讯28at.com

const Item = (props) => {  const [counter, setCounter] = useState(0)  if (!props.api) {    useEffect(() => {      console.log('useEffect 在 if 中执行')    }, [counter])    return <div>nothing</div>  }  console.log('初始化时这里是否执行')  const joke = use(props.api)  return (    <div className='a_value' onClick={() => setCounter(counter + 1)}>{joke.value}</div>  )}

此时一个很明显的问题就是,if 内部在 UI 逻辑上本和外部是互斥的关系,但是我们在状态逻辑上却相互关联。因此这个之后,代码执行就会报错,明确的告诉你这种写法不合理。zGj28资讯网——每日最新资讯28at.com

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

非常的方便省事。zGj28资讯网——每日最新资讯28at.com

当然这样写会造成冗余的接口请求执行。因此我们可以稍作调整就可以了。zGj28资讯网——每日最新资讯28at.com

这里需要根据需求调整,案例只做演示。zGj28资讯网——每日最新资讯28at.com

const _initApi = getApi()function Index() {  const [api, setApi] = useState(_initApi)  ...}

OK,今天的案例就介绍到这里,后续的章节我们还会继续更多的实战案例的分析。zGj28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-92464-0.html喔!React19 中的 Hook 可以写在 If 条件判断中了。Use 实践:点击按钮更新数据

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

上一篇: 解密Tenacity:Python中最强大的重试库

下一篇: 关于 Python 数据分析的 15 个 NumPy 应用

标签:
  • 热门焦点
  • Find N3入网:最高支持16+1TB

    OPPO将于近期登场的Find N3折叠屏目前已经正式入网,型号为PHN110。本次Find N3在外观方面相比前两代有很大的变化,不再是小号的横向折叠屏,而是跟别的厂商一样采用了较为常见的
  • 消息称迪士尼要拍真人版《魔发奇缘》:女主可能也找黑人演员

    8月5日消息,迪士尼确实有点忙,忙着将不少动画改成真人版,继《美人鱼》后,真人版《白雪公主》、《魔发奇缘》也在路上了。据外媒消息称,迪士尼将打造真人版
  • 轿车从天而降电动车主被撞身亡 超速抢道所致:现场视频让网友吵翻

    近日,上海青浦区法院判决轿车从天而降电动车主被撞身亡案,轿车车主被判有期徒刑一年。案件显示当时男子驾驶轿车在上海某路段行驶,前车忽然转弯提速超车,
  • 摸鱼心法第一章——和配置文件说拜拜

    为了能摸鱼我们团队做了容器化,但是带来的问题是服务配置文件很麻烦,然后大家在群里进行了“亲切友好”的沟通图片图片图片图片对比就对比,简单对比下独立配置中心和k8s作为配
  • 每天一道面试题-CPU伪共享

    前言:了不起:又到了每天一到面试题的时候了!学弟,最近学习的怎么样啊 了不起学弟:最近学习的还不错,每天都在学习,每天都在进步! 了不起:那你最近学习的什么呢? 了不起学弟:最近在学习C
  • 腾讯盖楼,字节拆墙

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之&ldquo;想重温暴刷深渊、30+技能搭配暴搓到爽的游戏体验吗?一起上晶核,即刻暴打!&rdquo;曾凭借直播腾讯旗下代理格斗游戏《DNF》一
  • 华为发布HarmonyOS 4:更好玩、更流畅、更安全

    在8月4日的华为开发者大会2023(HDC.Together)大会上,HarmonyOS 4正式发布。自2019年发布以来,HarmonyOS一直以用户为中心,经历四年多的发展HarmonyOS已
  • 首发天玑9200+ iQOO Neo8系列发布首销售价2299元起

    2023年5月23日晚,iQOO Neo8系列正式发布。其中,Neo系列首款Pro之作——iQOO Neo8 Pro强悍登场,限时售价3099元起;价位段最强性能手机iQOO Neo8同期上市
  • SN570 NVMe SSD固态硬盘 价格与性能兼具

    SN570 NVMe SSD固态硬盘是西部数据发布的最新一代WD Blue系列的固态硬盘,不仅闪存技术更为精进,性能也得到了进一步的跃升。WD Blue SN570 NVMe SSD的包装外
Top