我老板:你根本不懂 React!

news2025/1/22 20:52:24

前言

我已经使用 React 多年,我确信我非常了解它,但最近我的老板对我说,“你根本不知道 React,你对它一无所知。”

我很生他的气,但他指出了我程序中的三个漏洞。我现在把它记录下来,也分享给还不知道的小伙伴。

1、你知道“&&”的用法吗?

在React程序中,我经常使用“&&”运算符来决定是否显示内容,具体方式如下:

const App = () => {
  const [ list, setList ] = useState([])

  // Simulation request data
  setTimeout(() => {
    setList([ 'fatfish', 'medium' ])
  }, 2000)

  return (
    <div className="app">{ list.length && <List /> }</div>
  )
}

我老板:“你不知道&&”运算符的特点吗?当请求还没有成功返回时,会直接渲染“0”。

我不服气,因为我一直都是这样写代码,从来没有犯过错误。为了证明老大错了,我写了下面的例子。

const List = ({ list = [] }) => {
  return (
    <div className="name-list-container">
      {
        list.map((name) => {
          return <div className="name-list-item">{ name }</div>
        })
      }
    </div>
  )
}

const App = () => {
  const [ list, setList ] = React.useState([ ])

  // Simulation request data
  setTimeout(() => {
    setList([ 'fatfish', 'medium' ])  
  }, 3000)

  return (
    list.length && <List list={ list }/>
  )
}

ReactDOM.render(<App />, document.getElementById('app'))

我的天啊!老大说的对,一开始页面显示0,3秒后显示列表。

为什么?

来自 MDN的提示:“当且仅当所有操作数都为真时,一组布尔操作数的逻辑与 (&&) 运算符(逻辑合取)才为真。否则就是假的。”

更一般地,运算符返回从左到右计算时遇到的第一个假操作数的值,或者如果它们都是真值,则返回最后一个操作数的值。

例子如下:

const x1 = 0
const x2 = 'fatfish'
const x3 = 1
const x4 = 'medium'
console.log(x1 && x2) // 0
console.log(x3 && x4) // medium

现在我终于明白为什么写这样的代码会导致错误。原因如下:

list.length && <List list={ list } /> 
0 && <List list={ list } /> // 0

如何解决?

我找到了三种方法来解决这个问题。我希望你不要犯和我一样的错误,祝福你。

// 1. Convert list.length to boolean
!!list.length && <List list={ list }/>

// 2. Use ternary expressions and null
list.length ? <List list={ list }/> : null

// 3. Controlled by specific logic
list.length >= 1 && <List list={ list }/>

2.“props.children”的奇怪行为

我猜你写过类似的代码。当向组件传递内容时,会显示“children”。如果没有,将显示一个空的工具提示。像下面这样:

const Container = ({ children }) => {
  if (children) {
    return (
      <div className="children-container">
        <p>The content of children is:</p>
        { children }
      </div>
    ) 
  } else {
    return (
      <div className="empty">empty</div>
    )
  }
}

我的老板:“你要小心使用‘children’属性,它会导致逻辑异常!就像在以下情况中一样。”

1).清空列表数据

你认为这个例子会显示什么——“空”?

不幸的是,答案是另一个。你是不是也觉得不可思议?朋友们,我们一定要非常小心地使用 props.children。否则,老板可能会扣你的工资。

const Container = ({ children }) => {
  if (children) {
    return (
      <div className="children-container">
        <p>The content of children is:</p>
        { children }
      </div>
    ) 
  } else {
    return (
      <div className="empty">empty</div>
    )
  }
}
const App = () => {
  const [ list, setList ] = React.useState([])

  return (
    <Container>
      {
        list.map((name) => {
          return <div className="name-item">{ name }</div>  
        })
      }
    </Container>
  )
}
ReactDOM.render(<App />, document.getElementById('app'))

为什么?

让我们向“Container”组件添加一行代码,并尝试打印children是什么!

const Container = ({ children }) => {
  console.log(children, 'children')
  // ...
}

是的,你是对的。此时“children”为空数组,所以显示“children的内容为:”而不是“empty”。

如何解决?

使用 React.Children.toArray 解决这个问题会很容易,然后你会看到显示“empty”。所以如果你真的需要用children作为条件判断,我建议你使用这个方法!

const Container = ({ children }) => {
  // if (children) {
  // Pay attention here
  if (React.Children.toArray(children).length) {  
    return (
      <div className="children-container">
        <p>The content of children is:</p>
        { children }
      </div>
    ) 
  } else {
    return (
      <div className="empty">empty</div>
    )
  }
}

3.关于挂载和更新的问题

在 React 中通过状态来切换组件是很常见的,但是,这个小东西也会让你感到困惑。

在下面的代码中,你认为当你切换name的值时,一个Demo组件会被卸载,另一个会被挂载吗?

class Demo extends React.Component {
  componentDidMount() {
    console.log('componentDidMount', this.props.name);
  }
  componentDidUpdate() {
    console.log('componentDidUpdate', this.props.name);
  }

  render () {
    return (
      <div>
        { this.props.name }
      </div>
    )
  }
}
const App = () => {
  const [ name, setName ] = React.useState('fatfish')
  const onClick = () => {
    setName(name === 'fatfish' ? 'medium' : 'fatfish')
  }
  return (
    <div className="app">
      {
        name === 'fatfish' ? 
          <Demo name={ name } /> : 
          <Demo name={ name } />
      }
      <button onClick={ onClick }>click</button>
    </div>
  )
}
ReactDOM.render(<App />, document.getElementById('app'))

我录制了一个简短的 gif 给你真相。

你也可以通过 CodePen 试试,https://codepen.io/qianlong/pen/NWywodV

为什么?

虽然,我们写了两个 Demo 组件,假设它们会分别挂载和更新,但 React 认为它们是同一个组件,所以 componentDidMount 只会执行一次。

如何解决?

但是当我们要写两个相同的组件但是传递不同的参数时,我们应该怎么办呢?

是的,你应该为这两个组件添加不同的键,这样 React 就会认为它们是不同的组件。componentDidMount 也会单独执行。

我们试试看:

//...
// Pay attention here
name === 'fatfish' ? <Demo key="1" name={ name } /> : <Demo key="2" name={ name } />
//...

你也可以通过 CodePen 试试,https://codepen.io/qianlong/pen/NWywodV

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

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

相关文章

用好ChatGPT,毕业直接走上人生巅峰

毕业论文交上去了&#xff0c;学分也攒齐了。考研没上岸的准毕业生们接下来要面对的不是惨烈的秋招&#xff0c;就是蹲家准备二战。生活终于要对各位小可爱们动手啦&#xff01; 不想默默承受社会的毒打&#xff1f; 不愿在屡战屡败屡败屡战的压力下秃头&#xff1f; 想必各位…

API 都有这些功能,你真的都知道么?

API&#xff08;应用程序编程接口&#xff09;可以提供以下功能&#xff1a; 数据传输&#xff1a;API可以在应用程序之间传输数据&#xff0c;包括发送和获取数据、更新数据等。 访问功能: API 可以调用另一个系统或应用程序的某些功能&#xff0c;例如获取天气&#xff0c;查…

基于无线传感器网络(WSN) 查找两个节点之间的最短路径并发送数据(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 本代码基于无线传感器网络&#xff0c;在两个节点&#xff08;源节点和目标节点&#xff09;之间找到最短路径&#xff0c;并开…

Java学习过程(韩顺平661-665)

网络通信是指在计算机网络中&#xff0c;通过网络连接的设备之间进行数据交换的过程。网络通信可以分为两种类型&#xff1a;有线网络通信和无线网络通信。 有线网络通信主要通过物理介质&#xff08;如光纤、双绞线等&#xff09;来传输数据&#xff0c;其中最常用的协议是以…

数字孪生新能源智慧充电桩Web3D可视化运维系统

放眼全球&#xff0c;近十年来&#xff0c;新能源汽车赛道堪称“热得发烫”。伴随着进入成年期的新能源汽车行业对相关配套设备支撑水平的提升&#xff0c;作为其“新基建”的充电桩领域表现更为突出的价值势能。过去&#xff0c;在一系列补贴政策和资本刺激下&#xff0c;充电…

七种MOS管栅极驱动电路

01 直接驱动 首先说一下电源IC直接驱动&#xff0c;下图是我们最常用的直接驱动方式&#xff0c;在这类方式中&#xff0c;我们由于驱动电路未做过多处理&#xff0c;因此我们进行PCB LAYOUT时要尽量进行优化。如缩短IC至MOSFET的栅极走线长度&#xff0c;增加走线宽度&#x…

《商用密码应用与安全性评估》第三章商用密码标准与产品应用3.4商用密码标准与产品

一、智能IC卡标准与产品 智能IC卡的分类 存储器卡&#xff1a;内部一般不包含密码安全机制&#xff0c;不具备信息处理能力&#xff0c;外部可对片内信息任意存取&#xff0c;因此存储器卡一般用于存放不需要保密的信息逻辑加密卡&#xff1a;逻辑加密卡内除了具有非易失性存…

redis缓存生产实践(一)---大key压缩

文章目录 前言一、缓存到底是使用String还是hash我该如何选择二、什么是大key及其影响2.1 什么是 Redis 大 key&#xff1f;2.2 大key带来的影响 三、大key压缩3.1 注解标记可能需要压缩的数据3.2 获取注解信息判断内存占用大小3.2 判断对象占用内存3.2 gzip压缩json3.2 判断当…

Reid之损失函数理论学习讲解

基于深度学习的Reid主要流程为输入图像-->CNN(提取特征)-->Global average pooling-->特征向量&#xff0c;将用这些特征来衡量图像的相似情况。并用这些特征进行检索&#xff0c;返回分类情况。 在训练网络的时候需要涉及损失函数&#xff0c;因此就引出了表征学习和…

大数据专业好找工作么

现在&#xff0c;在数字化转型的推动下&#xff0c;越来越多的企业意识到大数据的魅力&#xff0c;并不断在这个领域投入资金&#xff0c;Python大数据开发相关人才也备受青睐&#xff01; 学Python之前&#xff1a;这玩意真有传说中那么好么&#xff1f; 学Python之后&#…

【browser】浏览器跨域处理

好久没有更新博客了&#xff0c;前段时间在疯狂面试&#xff0c;最近工作了才有时间来写博客。 准备来讲讲面试里常问到的跨域处理吧。 说到跨域&#xff0c;我们可能会下意思的说出jsonp&#xff0c;服务端配置cors&#xff0c;node配置代理等&#xff0c;再多了&#xff0c;我…

加密脱胎于去中心化理想,但力求合规 细数各国政府态度之演变

比特币诞生之始&#xff0c;只是极客文化圈内流行的小众货币。如今&#xff0c;加密市场已经发展到无法忽视的程度&#xff0c;虽然全球仍未对加密货币形成共识&#xff0c;但监管已成为各国政府不得不考虑的问题。 美国&#xff1a;监管愈发模糊且不可测 美国始终是加密领域全…

八股文(Mybatis)

文章目录 1. Mybatis缓存机制2. 动态SQL语句3. 分页3. 1 几种分页方式3.2 MyBatis 是如何进行分页的&#xff1f;分页插件的原理是什么&#xff1f;3.3 逻辑分页和物理分页 1. Mybatis缓存机制 作用&#xff1a;避免每次都去查db 一级缓存是SqlSession级别的缓存&#xff0c;也…

Mysql统计分组后每组数据与每组数量区别

下边统计的是分组后每组的数量&#xff1a;结果是多个 select p.id (count(*)) from p group by p.id 如果想统计分组后&#xff0c;有多个分组&#xff0c;需要如下执行&#xff1a; select count(*) from (select p.id (count(*)) from p group by p.id) as a 此外&#xf…

大数据之Hadoop数据仓库Hive

目录&#xff1a; 一、简介二、HQL的执行流程三、索引四、索引案例五、Hive常用DDL操作六、Hive 常用DML操作七、查询结果插入到表八、更新和删除操作待完善。。。 一、简介 Hive 是一个构建在 Hadoop 之上的数据仓库&#xff0c;它可以将结构化的数据文件映射成表&#xff0c…

【Linux】线程-线程安全之互斥

操作系统核心数centos 3.10.032位单核 线程之线程安全 线程不安全的现象互斥死锁线程饥饿 线程不安全的现象 进程线程的背景概念&#xff1a; 临界资源&#xff1a;多线程执行流之间共享的资源 临界区&#xff1a;每个线程内部&#xff0c;访问临界资源的代码 互斥&#xff1a…

设计模式——责任链

目录 1、传统方案&#xff0c;OA系统的采购审批项目 2、职责链模式基本介绍 3、职责链模式解决 OA 系统采购审批项目 4、职责链模式在 SpringMVC 框架应用的源码分析 责任链模式类似一个链表&#xff0c;每个具体处理人层层判断对请求的处理权限&#xff0c;没权限的话把请…

基于C++/CLI实现C#调用C++类对象过程中的注意事项

目录 一、基于C/CLI 的调用原理二、注意事项如何基于VS2010完成上述一系列开发过程1、生成C应用程序&#xff08;非托管代码&#xff09;2、基于C/CLI生成托管代码3、C#调用 三、C/CLI与COM组件对比 一、基于C/CLI 的调用原理 C/CLI &#xff08;Common Language Infrastructu…

阿里P7晒出工资单:狠补了这个,真香...

据阿里HR部门发布的最新信息&#xff0c;2023年招聘岗位数将扩招3000&#xff0b;。但就2022年就业形势来看&#xff0c;大厂缩招裁员导致优质岗位竞争变得更加激烈&#xff0c;2023开年以来&#xff0c;也有不少大厂纷纷传来裁员的消息&#xff01;除了对面试者技术的要求变高…

Netty BIO/NIO/AIO介绍

概念介绍 1、 BIO(blocking I/O):同步阻塞IO,也即是传统的I/O。 2、 NIO (non-blocking IO): 也即是New I/O,使用它可以提供非阻塞式的高伸缩性网络。 3、AIO 即 NIO2.0, 叫做异步不阻塞的 IO。 AIO 引入异步通道的概念, 采用了 Proactor 模式, 简化了程序编写,有…