之前写的 JSX 的条件语句竟然存在那么多 Bug?

853f7f810e408ab303c7c73db56b2a7d.gif

作者 | 零一

来源 | 前端印象

今天的主题是:关于 JSX 的条件语句,你不知道3件事

一、&&隐藏大坑

JSX 里写条件语句,&& 应该是用的最多的了,例如:

function Demo () {// ...省略一些代码return (<div>{isShow && <Child/>}</div>)
}

这样写确实非常简单易懂,但也存在隐藏的踩坑点,那就是 &&逻辑运算符的工作原理

&& 逻辑运算符工作原理: 例如 A && B ,当 A 隐式转换后为 true 时,则返回 B;当 A 隐式转换后为 false 时,则返回 A

举个例子🌰:

const A = 0
const B = 1const C = A && B   // 0
const D = B && A   // 0

所以有一种场景下,我们用 && 符号做条件判断渲染会有问题:有一个列表,当有列表数据时,展示列表里的内容;当没有列表数据时,则什么都不展示

function List () {//...
}function App () {const [list, setList] = useState([])useEffect(() => {// 请求列表数据// ...}, [])return (<div>{list.length && <List data={list} />}</div>)
}

代码看起来没什么问题,逻辑也说得通(当 list 有具体数据时,展示 <List/> 组件),但其实是有问题的,此时页面长这个样:

4e42c4aa937ffb15efc7fb3126077a25.png

为什么? 这就是刚才提到的 && 的工作原理了,当咱们未请求数据前,list = [] ,即 list.length = 0,那么 list.length && <List data={list} />  最终返回的就是 0 了,所以自然而然的 0 就出现在了页面中

这一定不是你想要的,下面提出一些解决方案和建议吧:

  1. 用三元运算符,即 list.length ? <List data={list} /> : null

  2. 两次取反,即 !!list.length && <List data={list} />

  3. 直接给出具体的判断逻辑,即 list.length > 0 && <List data={list} />

当然了,如果判断条件本来就是布尔值的话,那就可以忽略这一条了

二、Children作判断条件

在某些场景下我们可能会写一个组件来处理逻辑,例如:

function Wrap (props) {if (props.children) {return (<div><p>当前内容为:</p><div>{props.children}</div></div>)} else {return (<div>nothing</div>)}
}function App () {return (<Wrap><div>零一</div></Wrap>)
}

这段代码看起来也是毫无问题(当有传递给 <Wrap/> 组件 children 属性时,直接展示内容;否则展示 nothing ,表示当前为空),但其实存在很多漏洞情况,例如:

function App () {return (<Wrap>{list.map(item => <span>{item}</span>)}</Wrap>)
}

假设此时变量list[] ,那么 Wrap 组件中接收到的 children 则也为 [],那么 if (props.children) 的判断结果也为 true,则页面会这样展示:

76a1a2d3ea8b737eeef03db3930c7c57.png

这显然不是我们想要的结果。我们想要的效果是:当接收到空数组时,也展示 nothing ,即为空

有什么解决方案呢?

React 提供了现成的用于处理 children的 API:

  • React.Children.map

  • React.Children.forEach

  • React.Children.count

  • React.Children.only

  • React.Children.toArray

这里就不一一介绍每个的作用了,想要了解的可以直接去官网看:https://zh-hans.reactjs.org/docs/react-api.html#reactchildren

我们直接挑重点说,可以直接用 React.Children.toArray 来做处理,该方法可以把 children 统一变成数组的形式

还是用刚才的那个例子,我们改造一下看看返回了什么:

import { Children } from 'react'function Wrap (props) {// 用 Children.toArray 来处理 props.childrenif (Children.toArray(props.children).length) {return (<div><p>当前内容为:</p><div>{props.children}</div></div>)} else {return (<div>nothing</div>)}
}function App () {return (<Wrap>{ // 返回空数组[].map(item => <span>{item}</span>)}</Wrap>)
}

此时页面展示的是:

70fa6bf25b104445e336bcd167ca96c0.png

为什么会这样呢?打个断点进去看了一下 React.Children.toArray 大致都做了什么处理,这里简单总结一下:将 children 传过来的每个元素都放到一个数组中再返回,并会过滤掉空数组、Boolean、undefined

所以我们刚才的例子中,空数组直接被过滤掉了。我们再来验证一下 React.Children.toArray 的强大,举个例子🌰

function App () {return (<Wrap>{false && <span>作者:零一</span>}{true}{ // 返回空数组[].map(item => <span>{item}</span>)}{{}?.name}</Wrap>)
}

这种情况,<Wrap/> 组件接收到的 children 值应为:

[false,true,[],undefined,
]

那么页面展示的是什么呢?

8a7aa0a8b30c0fad885b7a81ec142a5c.png

是的,还是nothing,因为这四种情况的值全都被 React.Children.toArray 给过滤掉了,最终返回的值为 [] ,这也十分符合我们开发时的预期

所以如果你真的需要把 children 作为条件判断的依据的话,我建议是用这个方法!

三、挂载与更新

三元运算符在 JSX 中经常被我们拿来用于两种不同状态的组件切换,例如:

import { Component, useState } from 'react'class Child extends Component {componentDidMount() {console.log('挂载', this.props.name, this.props.age);}componentDidUpdate() {console.log('更新', this.props.name, this.props.age);}render () {const { name, age } = this.propsreturn (<div><p>{name}</p><p>{age}</p></div>)}
}function App () {const [year, setYear] = useState('1999')return (<div>{ year === '1999' ? <Child name="零一" age={1} />: <Child name="01" age={23} />}<button onClick={() => {setYear(year === '1999' ? '2022' : '1999')}}>切换</button></div>)
}

看到这个代码,你是不是觉得当变量 year 切换时,一个组件会卸载,另一个组件会挂载?但其实不是,我们来验证一下:

03ba3a774f314c1ca12f9ef4cbac59de.gif

可以看到,我们在切换了变量 year 时,<Child/> 组件只挂载了一次,而不是不停地挂载、卸载。其实这是React做的处理,虽然写了两个 <Child/> 组件,但React只认为是一个,并直接进行更新,即上述代码等价于:

// ... 省略大部分代码
function App () {// ...return (<div><Child name={year === '1999' ? "零一" : "01"} age={year === '1999' ? 1 : 23} />// ...</div>)
}

这种情况需要特别注意,当你真的想写两次同一个组件并传递不同的参数时,你可以给这两个组件赋予不同的 key ,那么React就不会认为它俩是同一个组件实例了,例如:

function App () {// ...return (<div>{ year === '1999' ? <Child name="零一" age={1} key="0"/>: <Child name="01" age={23} key="1"/>}</div>)
}

如果本意就是不想让两个组件实例不停卸载和挂载,那么就不需要做额外操作了~

dc3f0ae114327d4c288891e1526a72ff.gif

往期推荐

好难啊……一个 try-catch 问出这么多花样

k8s集群居然可以图形化安装了?

用了HTTPS,没想到还是被监控了

将 k8s 制作成 3D 射击游戏,好玩到停不下来

17b2d41486c3b868e9a618c6f74e5a58.gif

点分享

4b0b3ca0ec659e4c391b78a3ebe13b39.gif

点收藏

0c58a1a5f14c95d7dc8a1e0ab2c7e959.gif

点点赞

c98d1490f65e40870d51fe68b396c2bf.gif

点在看

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

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

相关文章

如何高效学习 Kubernetes 知识图谱?

简介&#xff1a; Kubernetes 知识图谱遵循云原生人才学习路径搭建课程体系框架&#xff0c;及人才发展路线设置不同阶段&#xff0c;由浅入深&#xff0c;帮助云原生人才学习容器基础、Kuternetes 网络、存储、资源对象、服务发现、应用编排与管理等 Kubernetes 完整技术栈内容…

中科院信工所经验_2021中科院信息工程研究所电子信息专业考研经验指导分享...

一、在计算机如此火热的今天&#xff0c;为什么选择要读研&#xff1f;我是一个乐观主义者&#xff0c;上大学以来我一直庆幸自己在高考结束填志愿的时候选择了计算机专业&#xff0c;更庆幸报考了湖南大学信息科学与工程学院&#xff0c;高考仅仅一分的优势把我送到了最美的学…

极验创始人吴渊:恶意流量威胁新趋势,揭秘网络黑产3大核心本质

记者 | 邓晓娟出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;天下没有免费的午餐&#xff0c;更没有免费的流量。以电商为例&#xff0c;最疯狂的时候&#xff0c;某电商平台单个获客成本接近400元。作为互联网的稀缺资源&#xff0c;流量的成本不断冲击着…

如何将一棵LSM-Tree塞进NVM

简介&#xff1a; 随着非易失内存产品的商业化推广&#xff0c;我们对于其在云原生数据库中大规模推广的潜力越来越有兴趣。X-Engine是阿里云数据库产品事业部PolarDB新型存储引擎团队研发的一个LSM-tree存储引擎&#xff0c;目前在阿里云PolarDB产品上提供对外服务。我们以X-E…

再见了,我的散装研发管理平台;再见了,4台ECS!

简介&#xff1a; 目前云效全家桶的功能相对来说比较适合个人开发或者中小团队的群体&#xff0c;如果你此时正在为搭建这类管理平台做选型&#xff0c;同时预算和人力都捉襟见肘&#xff0c;那么不妨试试云效这个产品&#xff01;一起白嫖一起爽&#xff01;尤其服务器资源在阿…

15拆分成3个不同的自然数_17个数学重点知识点汇总,一篇搞定小升初

更多电子版学习资料请关注公众号&#xff1a;小学资源园地1体积和表面积三角形的面积底高2。公式 S ah2正方形的面积边长边长 公式 S a2长方形的面积长宽 公式 S ab平行四边形的面积底高 公式 S ah梯形的面积(上底下底)高2 公式 S(ab)h2内角和&#xff1a;三角形的内角和180度。…

走进统信软件,读懂国产操作系统新生态建设

回顾国际 2021 操作系统领域发展&#xff0c;有起伏有波澜&#xff1a;开源操作系统 Linux 迎来 30 岁&#xff0c;全球超级计算机 500 强和超过 70% 的智能手机都运行其上&#xff1b;CentOS 突然宣布 CentOS 8 停止维护&#xff0c;不少企业不得不面临迁移难题…… 反观国产…

Serverless 工程实践 | Serverless 应用开发观念的转变

简介&#xff1a; Serverless 架构带来的除了一种新的架构、一种新的编程范式&#xff0c;还包括思路上的转变&#xff0c;尤其是开发过程中的一些思路转变。有人说要把 Serverless 架构看成一种天然的分布式架构&#xff0c;需要用分布式架构的思路去开发 Serverless 应用。诚…

中科院计算机所硕士导师,中科院计算技术研究所研究生导师介绍:毕经平

中科院计算技术研究所研究生导师介绍&#xff1a;毕经平简历:2002年7月于中国科学院计算所获得博士学位&#xff0c;同年9月被破格提拔为计算所副研究员&#xff0c;2008年3月被任命为博士生导师&#xff0c;2009年1月获得卢嘉锡青年人才奖作者佚名次阅读2014-05-15代表论著:1)…

bash: 未预期的符号 `( 附近有语法错误_安规群中关于泄漏电流测试、接地符号等相关的6个问题,快来围观大神的回答吧!...

【本文属"世界认证地图"原创&#xff0c;未经允许&#xff0c;请勿转载哦~~~】问题一群员提问&#xff1a;接地这样符合GB4706.1-2005的标准要求吗&#xff1f;图片由群友提供群友解答&#xff1a;接地符号标错地方&#xff0c;应该如下图图片由群友提供专家解答&…

多项“首次”落地 腾讯云数据库助力金融机构国产化

日前&#xff0c;IDC发布了《2021年上半年中国关系型数据库软件市场跟踪报告》&#xff0c;数据显示&#xff0c;我国关系型数据库市场规模迅速增长。2021上半年&#xff0c;中国关系型数据库软件市场规模为11.9亿美元&#xff0c;整体市场同比增长37.2%。IDC预测&#xff0c;2…

庖丁解牛-图解MySQL 8.0优化器查询转换篇

简介&#xff1a; 在《庖丁解牛-图解MySQL 8.0优化器查询解析篇》一文中我们重点介绍了MySQL最新版本8.0.25关于SQL基本元素表、列、函数、聚合、分组、排序等元素的解析、设置和转换过程&#xff0c;本篇我们继续来介绍更为复杂的子查询、分区表和JOIN的复杂转换过程。 作者 |…

hivesql修改字段类型_Hive SQL语法总结

Hive是一个数据仓库基础的应用工具&#xff0c;在Hadoop中用来处理结构化数据&#xff0c;它架构在Hadoop之上&#xff0c;通过SQL来对数据进行操作&#xff0c;了解SQL的人&#xff0c;学起来毫不费力。Hive 查询操作过程严格遵守Hadoop MapReduce 的作业执行模型&#xff0c;…

Cube 技术解读 | 支付宝新一代动态化技术架构与选型综述

简介&#xff1a; 支付宝客户端的动态化技术经历三个阶段&#xff1a;现阶段也就是第三阶段是实体组件部分光栅化的hybrid模式&#xff0c;Cube 就是该模式下的产物。 如标题所述&#xff0c;笔者将持续更新《Cube 技术解读》系列文章。本文为Cube系列首篇文章&#xff0c;后续…

阿里云数字巡展:“云上峰会”背后的秘密武器

简介&#xff1a; 近日&#xff0c;阿里云官网上线了叫做“数字巡展”的新产品&#xff0c;专为各行业在数字化创新提供解决方案。数字巡展&#xff0c;立足于设计创新&#xff0c;融合定制化虚拟空间、沉浸化技术体验、数字化企业营销三大核心能力&#xff0c;通过创意和技术优…

把所有圆圈连接起来的游戏_20个幼儿园体育小游戏教程

1、游戏《木头人》游戏规则&#xff1a;幼儿手拉手围成一个圆圈&#xff0c;边走边念儿歌"我是一个木头人&#xff0c;不会说话不会动&#xff0c;看谁坚持一分钟"念到最后一个字时所有幼儿摆出造型不动。老 师说时间到才能动&#xff0c;游戏反复进行。2、游戏《粘泡…

拒绝双写:巧用Lindorm数据订阅

简介&#xff1a; 本文介绍了双写场景的一致性问题&#xff0c;详细介绍了三种解决方案&#xff0c;并针对DB->Binlog->Kafka方案给出了Lindorm数据订阅的最佳实践 双写问题介绍 双写问题&#xff08;Dual Write Problem&#xff09;是指&#xff1a;需要同时修改两个独…

春节快到了,来写个烟花动效吧

作者 | Eason来源 | 程序员巴士2022虎年大吉&#xff0c;预祝各位小伙伴们新年快乐&#xff0c;这篇文章教大家如何在 Canvas 中实现高性能的烟花粒子特效&#xff0c;通过使用 Canvas BitmapShader GestureDetector技术栈&#xff0c;实现趣味 2D 春节烟花特效页面&#xff…

商用服务器系统比较好,商用服务器操作系统都用哪种

商用服务器操作系统都用哪种 内容精选换一换切换弹性云服务器操作系统。支持弹性云服务器数据盘不变的情况下&#xff0c;使用新镜像重装系统盘。调用该接口后&#xff0c;系统将卸载系统盘&#xff0c;然后使用新镜像重新创建系统盘&#xff0c;并挂载至弹性云服务器&#xff…

边缘使用 K8s 门槛太高?OpenYurt 这个功能帮你快速搭建集群!

简介&#xff1a; 为了降低 OpenYurt 的使用门槛&#xff0c;帮助更多地开发者快速上手 OpenYurt&#xff0c;社区提供了 OpenYurt 易用性工具 yurtctl。该工具致力于屏蔽 OpenYurt 集群创建的复杂性&#xff0c;帮助开发者在本地快速地搭建 OpenYurt 开发测试集群。 OpenYurt…