React的零渲染问题及源码分析
开门见山,先来看一张bug图(状态下面有个00)。
文章图片
预期是:状态为0时,2个组件不做渲染。
现状:状态为0时,2个组件不做渲染,但是渲染出了00。
- 零渲染 bug 代码
- 如何修复零渲染问题
- 初窥源码
- 源码疑惑
- 原因总结
- 源码实锤
看下下面这段代码,我们会经常这样写:
// bug代码 0
{obj?.count && {obj?.count}}
假如obj?.count为0,渲染结果为0。
这里不就1个0么,上面为什么是00呢。
// bug代码 00
{obj?.countFoo && {obj?.countFoo}}
{obj?.countBar && {obj?.countBar}}
当obj?.countFoo和obj?.countBar都为0时,渲染结果为00。
如何修复零渲染问题
{!!obj?.count && {obj?.count}}
或者
{obj?.count ? {obj?.count} : null}
或者
{Boolean(obj?.count) && {obj?.count}}
初窥源码 原因(点击类型查看源码):
React组件会渲染string,number。不会渲染null,undefined,boolean。
源码疑惑 既然boolean会被处理为null,那为什么
true &&
可以正常渲染呢?先说结论,因为进行了&&运算,React最终渲染的是jsx与计算后的结果。
const type = typeof children;
if (type === 'undefined' || type === 'boolean') {
// All of the above are perceived as null.
children = null;
}
也就是说 此处的children,是jsx计算后的结果。
举例如下:
// 可渲染值
1 && // => jsx计算结果为 ,因此渲染
"a string" && // => jsx计算结果为 ,因此渲染
0 && // => jsx计算结果为0,Renders '0'
true && // => jsx计算结果为 ,因此渲染 // 不可渲染值
false && // => jsx计算结果为false,因此什么都不渲染
null && // => jsx计算结果为null,因此什么都不渲染
undefined && // => jsx计算结果为undefined,因此什么都不渲染
原因总结 其实,根本不是React渲染什么的问题,而是&&操作符后返回值的问题。
所以,最根本是因为
- React渲染string,number,正常组件
- React不渲染undefined,boolean,null
{"1"} // 渲染为"1" {0} // 渲染为0 {
} // 假设为正常组件,渲染为 {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 '';
}
【React的零渲染问题及源码分析】对于html标签渲染空字符串而言,空字符串会被忽略。
例如
""
会被渲染为
完整流程为
{null} =>{""} => nothing
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量