「同一位置」之定义,不仅取决于组件所处位置之JSX层级
还取决于组件所处层级中,与其他组件的先后顺序。
return (
<div>
{isPlayerA ? (
<Counter person="Taylor" />
) : (
<Counter person="Sarah" />
)}
<button onClick={() => {
setIsPlayerA(!isPlayerA);
}}>
Next player!
</button>
</div>
);
无论isPlayerA是true还是false,<div>下都只有两个元素,一个组件<Counter/>,一个<button>。
return (
<div>
{isPlayerA &&
<Counter person="Taylor" />
}
{!isPlayerA &&
<Counter person="Sarah" />
}
<button onClick={() => {
setIsPlayerA(!isPlayerA);
}}>
Next player!
</button>
</div>
);
当isPlayerA为true时:
<div>
<Counter person="Taylor" />
{false}
<button onClick={() => {
setIsPlayerA(!isPlayerA);
}}>
Next player!
</button>
</div>
当isPlayerA为false时:
<div>
{false}
<Counter person="Sarah" />
<button onClick={() => {
setIsPlayerA(!isPlayerA);
}}>
Next player!
</button>
</div>
<Counter/>组件所处顺序不同,React就不会保留它的状态。
1
huangzhiyia 2023-11-04 17:00:49 +08:00 1
区别是这个地方
{isPlayerA ? ( <Counter person="Taylor" /> ) : ( <Counter person="Sarah" /> )} 这个状态会保留 {isPlayerA && <Counter person="Taylor" /> } {!isPlayerA && <Counter person="Sarah" /> } 这个状态不会保留 |
2
VisualStudioCode OP |
3
thevita 2023-11-04 17:39:42 +08:00
这样,你把 render tree 分别打出来看就明白了
``` ..... const r = ( <div> {isPlayerA ? <Counter person="Taylor" /> : <Counter person="Sarah" />} <button onClick={() => { setIsPlayerA(!isPlayerA); }} > Next player! </button> </div> ); console.log(r); return r; ...... ``` https://codesandbox.io/s/shy-firefly-3xt4ck props: children: Array(2) 0: {$$typeof: Symbol(react.element), key: null, ref: null, props: {…}, type: ƒ, …} 1: {$$typeof: Symbol(react.element), type: 'button', key: null, ref: null, props: {…}, …} https://codesandbox.io/s/quizzical-artem-5j8xqk props: children: Array(2) 0: {$$typeof: Symbol(react.element), key: null, ref: null, props: {…}, type: ƒ, …} 1: false 3: {$$typeof: Symbol(react.element), type: 'button', key: null, ref: null, props: {…}, …} render tree 是不一样的, 后面 diff 的时候 前一种 是没办法识别 Counter 这个 element 的变化的 ps: 不写 react ,描述按我自己理解来的,但大概应该就是这个样子 |
4
codehz 2023-11-04 17:45:19 +08:00 via iPhone
你想哈既然 jsx 本质就是 js 语法糖,那如果直接用?:语法 react 怎么知道它是改了整个组件,还是单纯只改了 props 呢(组件相同,仅 props 不同,没有 key 的情况下如何区分?)
而&&的写法,因为分属于数组的两个不同位置,react 可以直接根据位置来推断是不是同一个组件 这与其说是 react 特意设计的特性,不如说是 jsx 语法转换的副作用(虽然 jsx 严格意义上也算是 react 的设计),不过好歹 react 给了一个文档说了 |
5
vivipure 2023-11-04 17:48:06 +08:00
这东西太不符合直觉了,按理来说每个组件都应该是自己的状态的,这个切换还能保留状态。
|
6
hua123s 2023-11-04 18:02:08 +08:00 via Android
就是因为 key 不一样,所以状态丢了。
|
7
noe132 2023-11-04 18:51:44 +08:00
第一种写法和
<Counter person={isPlayerA ? "Taylor": "Sarah"} /> 是等价的。 React 对于同组件同位置的节点会在重新渲染时会被认为是同一个实例。 区分不同实例的方式是使用不同的 key 。 |
8
lisongeee 2023-11-04 19:40:28 +08:00 3
把 jsx 转换为 原生 js 就很直白了
![image]( https://github.com/gkd-kit/gkd/assets/38517192/d586fcd2-9539-4b94-87b0-3c6a8886297e) ![image]( https://github.com/gkd-kit/gkd/assets/38517192/74700d26-b9fc-4bc2-9b13-995d17db5639) 你的第二个示例程序,返回的数组中当 isPlayerA 真时是 [Fc, null],假时为 [null, Fc] 而第一个示例程序,返回的数组中当 isPlayerA 真时是 [Fc],假时为 [Fc],因此切换后状态不会丢失 |
9
RabbitDR 2023-11-04 20:01:29 +08:00
8 楼的图片很清晰了,前者通过三元算出来的在同一个位置,后者是真的两个不同的位置,这里的位置指 createElement 的入参。
|
10
VisualStudioCode OP |
11
VisualStudioCode OP |
12
lisongeee 2023-11-04 23:56:55 +08:00
|
13
SingeeKing 2023-11-05 02:59:54 +08:00
本质上就是 children 是一个数组,每个语句会被转换成 children 的一个成员
使用 ?: 时是一个语句,也就对应一个成员 使用 && 时是两个语句了,也就对应两个不同的成员了 |
14
HaroldFinchNYC 2023-11-05 09:03:14 +08:00
@SingeeKing +1
|
15
VisualStudioCode OP @vivipure
好吧,我也只是在学习中,不知道这一段文档是否跟快照机制有关。 |
16
VisualStudioCode OP 谢谢大家的帮助!我写在附言中写了个人总结。
@zmaplex @thevita @codehz @vivipure @hua123s @noe132 @lisongeee @RabbitDR @SingeeKing @HaroldFinchNYC @twelvechen @cugljd @netabare @lopssh @Mercpoff @finnlewis @ChellFong @19888888888x |