单刀直入,先来看一张bug图(状态上面有个00)。

预期是:状态为0时,2个组件不做渲染。
现状:状态为0时,2个组件不做渲染,然而渲染出了00。

  • 零渲染 bug 代码
  • 如何修复零渲染问题
  • 初窥源码
  • 源码纳闷
  • 起因总结
  • 源码实锤

零渲染 bug 代码

什么是React的零渲染问题?
看下上面这段代码,咱们会常常这样写:

// bug代码 0{obj?.count && <span>{obj?.count}</span>}

如果obj?.count为0,渲染后果为0。
这里不就1个0么,下面为什么是00呢。

// bug代码 00 {obj?.countFoo && <span>{obj?.countFoo}</span>}{obj?.countBar && <span>{obj?.countBar}</span>}

当obj?.countFoo和obj?.countBar都为0时,渲染后果为00。

如何修复零渲染问题

{!!obj?.count && <span>{obj?.count}</span>}

或者

{obj?.count ? <span>{obj?.count}</span> : null}

或者

{Boolean(obj?.count) && <span>{obj?.count}</span>}

初窥源码

起因(点击类型查看源码):
React组件会渲染string,number。不会渲染null,undefined,boolean。

源码纳闷

既然boolean会被解决为null,那为什么true && <FooComponent />能够失常渲染呢?
先说论断,因为进行了&&运算,React最终渲染的是jsx与计算后的后果。

const type = typeof children;if (type === 'undefined' || type === 'boolean') {    // All of the above are perceived as null.    children = null;}

也就是说 此处的children,是jsx计算后的后果。

举例如下:

// 可渲染值1 && <FooComponent /> // => jsx计算结果为<FooComponent />,因而渲染<FooComponent/>"a string" && <FooComponent /> // => jsx计算结果为<FooComponent />,因而渲染<FooComponent />0 && <FooComponent /> // => jsx计算结果为0,Renders '0'true && <FooComponent /> // => jsx计算结果为<FooComponent />,因而渲染<FooComponent />// 不可渲染值false && <FooComponent /> // => jsx计算结果为false,因而什么都不渲染null && <FooComponent /> // => jsx计算结果为null,因而什么都不渲染undefined && <FooComponent /> // => jsx计算结果为undefined,因而什么都不渲染

起因总结

其实,基本不是React渲染什么的问题,而是&&操作符后返回值的问题。
所以,最基本是因为

  • React渲染string,number,失常组件
  • React不渲染undefined,boolean,null

    {"1"} // 渲染为"1"{0} // 渲染为0{<FooComponent />} // 假如为失常组件,渲染为<FooComponent />{undefined} // 不渲染{true} // 不渲染{false} // 不渲染{null} // 不渲染

源码实锤

  const type = typeof children;  // React不渲染undefined,boolean  if (type === 'undefined' || type === 'boolean') {    // All of the above are perceived as null.    children = null;  }  let invokeCallback = false;  if (children === null) {    invokeCallback = true;  } else {    switch (type) {      case 'string':      case 'number':        // React渲染string,number        invokeCallback = true;         break;      case 'object':        // React渲染失常组件        switch ((children: any).$$typeof) {          case REACT_ELEMENT_TYPE:          case REACT_PORTAL_TYPE:            invokeCallback = true;        }    }  }

原始值为null,和undefined以及boolean最终被解决为null,React不渲染null的源码实锤呢?
源码地址:https://github.com/facebook/r...

  render(    child: ReactNode | null,    context: Object,    parentNamespace: string,  ): string {    if (typeof child === 'string' || typeof child === 'number') {      const text = '' + child;      if (text === '') {        return '';      }      this.previousWasTextNode = true;      return escapeTextForBrowser(text);    } else {      let nextChild;      ({child: nextChild, context} = resolve(child, context, this.threadID));      // React不渲染null      if (nextChild === null || nextChild === false) {        return '';      }

对于html标签渲染空字符串而言,空字符串会被疏忽。
例如<div>""</div>会被渲染为<div></div>
残缺流程为{null} =>{""} => nothing