小而美的系列教程,周末定时更新,后续会推出基于 React 从 0~1 开发的三方插件,如果有收获,记得给个点赞。
在文章开始前,先问大家一个问题,下面两种写法有差异吗?
const App = () => {
const[isPlayerA, setIsPlayerA] = useState(true);
const handleOnClick = () => setIsPlayerA(!isPlayerA);
return (
<>
<button onClick={handleOnClick}>Next player</button>
{isPlayerA ? (
<Counter name="Taylor" />
) : (
<Counter name="Sarah" />
)}
</>
);
};
const App = () => {
const[isPlayerA, setIsPlayerA] = useState(true);
const handleOnClick = () => setIsPlayerA(!isPlayerA);
return (
<>
<button onClick={handleOnClick}>Next player</button>
{isPlayerA && <Counter name="Taylor" />}
{!isPlayerA && <Counter name="Sarah" />}
</>
);
};
相信很多同学在日常开发中没太注意这类细节,又不是不能用!
两种其实是有差别的,当 Counter 内部有状态时,前者在切换 flag 时, Counter 内部状态会保持,而后者会重置状态。
const Counter = ({ name }: { name: string }) => {
const [count, setCount] = useState(0);
const handleOnClick = () => setCount(count + 1);
return (
<div>
<p>球员:{name}</p>
<p>成绩:{count}</p>
<button onClick={handleOnClick}>+1</button>
</div>
);
};
三元表达式:
&& 符:
看完表现,大家能猜到原因吗?
对于前者,不论 flag 是 true 还是 false,由于 Couter 在 UI Tree 里面的位置是一致的(推荐大家去了解下 UI Tree,和你想象的也许有差别),只有 props name 更新了,React 会认为它没有改变,所以状态被保留。
对于后者,你会不会也认为他俩在 UI Tree 里面是相同的?其实不是的,当 flag: true 的时候,并不会渲染Sarah,反之不会渲染Taylor;状态切换的时候存在销毁过程,销毁是会清除状态的。
如果我们既想用前者,又不想保留状态,该如何实现呢?方法比较多,我们介绍两种比较常见的。
- key
- 不同位置
key: 大家都不陌生,直接看示例
{isPlayerA ? (
<Counter key="Taylor" name="Taylor" />
) : (
<Counter key="Sarah" name="Sarah" />
)}
由于 key 不相同, React 会认为是 2 个不同的组件,切换的时候也会触发销毁,达到 reset state 的效果。
不同位置:我们可以用 div 和 article 包裹一下组件,由于 React 在做 diff 时发现元素类型不同,会将所有子元素直接移除,重新渲染,也可以达到 reset State 的效果。
{isPlayerA ? (
<div>
<Counter name="Taylor" />
</div>
) : (
<article>
<Counter key="Sarah" name="Sarah" />
</article>
)}
如果你意犹未尽:beta.reactjs.org/learn/prese…