react两种条件渲染方式为什么效果不同
- return内内联条件判断的表达式(比如三元表达式,&&,||之类的)
- return外条件判断, 返回不同结果
代码示例codesandbox
也可以直接看下面的代码(推荐直接打开上面的sandbox查看效果)
第一种方式在点击next的时候会重置score这个state, 比如<Test>
第二种方式则不会重置score, 比如<Test2>
为什么?
export default function App() {
return (
<div className="App">
<Test/>
<Test2/>
</div>
);
}
function Test() {
const [show, setShow] = useState(true);
return (
<div>
{show && <Counter id={1} />}
{show || <Counter id={2} />}
<br />
<label>
<input
type="checkbox"
checked={show}
onChange={(e) => {
setShow(e.target.checked);
}}
/>
Next
</label>
</div>
);
}
function Test2() {
const [show, setShow] = useState(true);
if (show) {
return (
<div>
<Counter id={1} />
<br />
<label>
<input
type="checkbox"
checked={show}
onChange={(e) => {
setShow(e.target.checked);
}}
/>
Next
</label>
</div>
);
}
return (
<div>
<Counter id={2} />
<br />
<label>
<input
type="checkbox"
checked={show}
onChange={(e) => {
setShow(e.target.checked);
}}
/>
Next
</label>
</div>
);
}
function Counter({ id }) {
const [score, setScore] = useState(0);
return (
<div style={{ display: "inline-block" }}>
<h1>{score}</h1>
<p>id:{id}</p>
<button onClick={() => setScore(score + 1)}>Add one</button>
</div>
);
}
这是节点有没有被复用而造成的问题
在你的例子
Test
中show变化前后的children数组分别是其中
boolean
类型的值会被忽略,所以只有Counter
组件会被渲染出来由于你没有给Counter元素指定显式的key所以在diff时React会用child在数组中的下标来作为他的key,所以Counter1
的key为0
,Counter2
的key为1,所以更新前后节点并不能被复用,所以Counter1
会被销毁,然后重新创建一个Counter2
在你的
Test2
例子中show变化前后的数组分别是[Counter1] ===> [Counter2]
所以走的是更新流程
Counter1
的状态会被保留要解决也很简单给
Counter1
和Counter2
一个显式的key就行,即将Test
中的那部分代码改成即可React的diff逻辑并不复杂,具体逻辑可以看这里