特定条件下尽量不要在react中使用&&

12,054 阅读3分钟

前沿

事情是这样的,在 react 中,我们通常使用 && 这种判断方式来达到 vue 中的 v-if 的效果,表示某一段 dom 元素到底在某些条件下到底要不要展示的问题

比如在 vue 中,你可以这样写,这段代码中 div 由于 v-if 取决于 visible 的值,通常是一个布尔值,但是即便是你把 visible 给成数字 0,这个 div 也是不展示的,所以你也可以用 v-if 判断 list.length,表示 list 的长度为 0 的时候不展示相关的 dom

<template>
  <div v-if="visible"></div
</template>

但是在 react 中,我们通常使用 && 来进行判断,如果条件成立,就渲染 && 后面的 dom 元素,这段代码中 h1 标签的展示取决于 visible

export default function App() {
  return (
    <div>
      {visible && <h1>Hello StackBlitz!</h1>}
      <p>Start editing to see some magic happen :)</p>
    </div>
  );
}

但是如果用 0 来判断的话就会出现异常

这样我在写这种代码的时候很容易出现问题,因为这样会在页面上显示一个 0

{list.length && <h1>Hello StackBlitz!</h1>}

原因

那为什么在 vue 中就可以呢?我们看一下 vue 中通过 v-if 最终会把代码编译成什么形式。按照刚才的例子,vue 的编译结果如下

render(_ctx, _cache, $props, $setup, $data, $options) {
  return visible ? (_openBlock(), _createBlock("div", { key: 0 }))
    : _createCommentVNode("v-if", true)
}

本质是一个三元运算符,所以会进行隐式类型转换,当 visible 是 true 的时候会进行 div 的创建,如果是 false,会在当前模版中创建一个注释节点(也可称为占位节点),长这样

react 中虽然是 jsx 的语法,但本质还是 js 基础的那一套,所以在开发的过程中,没有 vue 的模版语法,那要了解为什么 0 && 会出现问题,还得了解 && 的本质

&& 的本质

既然要提到 && 的本质,那说明这个问题并不是 react 的问题,对于 && 在 MDN 上的解释是

一般来说,当从左到右求值时,该操作符返回第一个假值操作数的值;如果它们都是真值,则返回最后一个操作数的值

其本质也就是从左到右对整个操作进行求值,遇到第一个假值就会立即返回,如果所有的操作都是真值,则返回最后一个操作值

同时我们要知道转换成 false 的有以下内容:

false/null/NaN/0/空字符串/undefined

所以这个时候,问题来了,虽然会进行隐式类型转换,但是 && 运算符会保留所有非布尔值并原样返回它们

"" && 1 // ''
0 && 1 // 0
NaN && 1 // NaN

所以你知道了当你在 react 中使用 && 的时候,当然不仅仅是 react,它会返回0

同样的对于 NaN 来说,他也会在页面上显示 NaN,一定要注意

如何解决

那这种情况怎么解决呢?

  1. 使用 !!

我们可以使用 !! 来将 0 转换成布尔类型

!!list.length && <Component list={list} />
  1. 修改判断条件,不依赖隐式类型转换
list.length >= 1 && <Component list={list} />
  1. 使用三元表达式,修改返回结果
list.length ? <Component list={list} /> : null
  1. 使用判断条件
if(list.length){return <Component list={list} />}
  1. Boolean 类型转换
Boolean(list.length) && <Component list={list} />

平时在用的时候,使用上述的方式最好对 && 操作符左侧的内容进行转换,得到想要的结果,而不是出现不可预料的问题