Straight to the point, let's first look at a bug map (there is a 00 below the status).
The expectation is: when the state is 0, the two components do not render.
Status: When the state is 0, the two components are not rendered, but 00 is rendered.
- Zero rendering bug code
- How to Fix Zero Rendering Issues
- First look at the source code
- Source code doubts
- Reason summary
- source code hammer
Zero rendering bug code
What is React's zero rendering issue?
Take a look at the following code, we will often write it like this:
// bug代码 0
{obj?.count && <span>{obj?.count}</span>}
If obj?.count is 0, the rendering result is 0.
Isn't there just one 0 here, why is it 00 above?
// bug代码 00
{obj?.countFoo && <span>{obj?.countFoo}</span>}
{obj?.countBar && <span>{obj?.countBar}</span>}
When both obj?.countFoo and obj?.countBar are 0, the rendering result is 00.
How to Fix Zero Rendering Issues
{!!obj?.count && <span>{obj?.count}</span>}
or
{obj?.count ? <span>{obj?.count}</span> : null}
or
{Boolean(obj?.count) && <span>{obj?.count}</span>}
First look at the source code
Reason (click the type to view the source code):
The React component will render string, number . Will not render null , undefined , boolean .
Source code doubts
Since boolean will be treated as null, why does true && <FooComponent />
render normally?
Let’s talk about the conclusion first, because of the && operation, React finally renders jsx and the calculated result.
const type = typeof children;
if (type === 'undefined' || type === 'boolean') {
// All of the above are perceived as null.
children = null;
}
That is to say, the children of here is the result of jsx calculation.
An example is as follows:
// 可渲染值
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,因此什么都不渲染
Reason summary
In fact, it is not the problem of React rendering at all, but the problem of the return value after the && operator.
Therefore, the most fundamental reason is that
- React render string, number, normal component
React doesn't render undefined, boolean, null
{"1"} // 渲染为"1" {0} // 渲染为0 {<FooComponent />} // 假设为正常组件,渲染为<FooComponent /> {undefined} // 不渲染 {true} // 不渲染 {false} // 不渲染 {null} // 不渲染
source code hammer
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;
}
}
}
The original value is null, and undefined and boolean are finally processed as null. React does not render the source code of null. What about ?
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 '';
}
For html tags to render empty strings, empty strings will be rendered, for example <div>""</div>
will be rendered as <div>""</div>
But for react the full flow is {null} =>{""} => nothing
For example the following:
<div>{''}</div> // => <div></div>
<div>{' '}</div> // => <div> </div>
So, How does React handle empty strings?
export function pushTextInstance(
target: Array<Chunk | PrecomputedChunk>,
text: string,
responseState: ResponseState,
): void {
if (text === '') {
// Empty text doesn't have a DOM node representation and the hydration is aware of this.
// 这句注释的意思是:空文本节点没有DOM节点表示,它属于textNode
return;
}
// TODO: Avoid adding a text separator in common cases.
target.push(stringToChunk(encodeHTMLTextNode(text)), textSeparator);
}
From the source code, we can see that for empty text nodes, React will return directly, and will not generate a text instance (TextInstance).
Looking forward to communicating with you and making progress together:
- WeChat public account: Dada big front end / excellent_developers
- Front-end Q&A mutual aid planet: t.zsxq.com/yBA2Biq
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。