这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战
翻译自:beta.reactjs.org/learn/state…
state 变量可能看起来像您可以读取和写入的常规 JavaScript 变量。但是,state 的行为更像是快照。设置它不会更改您已有的 state 变量,而是会触发重新渲染。
这个系列的文章你将学习到:
- 如何设置 state 的触发器进行重新 render
- state 何时以及如何更新
- 设置 state 后为什么状态不会立即更新
- 事件处理程序如何访问 state 的“快照”
系列文章
总结
- 设置 state 会进行新的 render。
- React 将 state 存储在组件之外,就像在架子上一样。
- 当您调用
useState
时,React 会为您提供这次 render 中 state 的快照。 - 变量和事件处理程序在 re-render 时不会“幸存”。每次 render 都有自己的事件处理程序。
- 每次 render(以及其中的函数)将始终“看到”React 赋予该 render 的 state 快照。
- 你可以在心里替换事件处理程序中的 state,类似于你对 render 出的 JSX 的看法。
- 过去创建的事件处理程序具有创建它们的时候 render 的 state 值。
实践 - 交通灯切换
学习完了这个系列的三篇文章,我们通过一个例子来加深印象吧~
这是一个人行横道灯组件,当按钮被按下时会切换:
import { useState } from 'react';
export default function TrafficLight() {
const [walk, setWalk] = useState(true);
function handleClick() {
setWalk(!walk);
}
return (
<>
<button onClick={handleClick}>
Change to {walk ? 'Stop' : 'Walk'}
</button>
<h1 style={{
color: walk ? 'darkgreen' : 'darkred'
}}>
{walk ? 'Walk' : 'Stop'}
</h1>
</>
);
}
复制代码
向单击处理程序添加 alert。当绿灯亮并显示“Walk,”时,点击按钮应该显示“Stop is next.”。当红灯亮并显示“Stop,”时,点击按钮应该显示“Walk is next.”。
把 alert 放在 setWalk
调用之前还是之后有区别吗?
3
2
1
解决方式:
import { useState } from 'react';
export default function TrafficLight() {
const [walk, setWalk] = useState(true);
function handleClick() {
setWalk(!walk);
alert(walk ? 'Stop is next' : 'Walk is next'); // 这里
}
return (
<>
<button onClick={handleClick}>
Change to {walk ? 'Stop' : 'Walk'}
</button>
<h1 style={{
color: walk ? 'darkgreen' : 'darkred'
}}>
{walk ? 'Walk' : 'Stop'}
</h1>
</>
);
}
复制代码
把它放在 setWalk
调用之前还是之后都没有区别,这次 render 的 walk
值是固定的。调用 setWalk
只会在下一次 render 更改它,但不会影响上一次 render 的事件处理程序。
这行代码乍一看似乎有悖常理:
alert(walk ? 'Stop is next' : 'Walk is next');
复制代码
但是如果你把它读成:“如果红绿灯显示‘Walk now’,那么消息应该是‘Stop is next’。”事件处理程序中的 walk
变量与 render 的 walk
值匹配并且不会改变。
您可以通过替换变量的方法来验证这是否正确。当 walk
为 true
时,你会得到:
<button onClick={() => {
setWalk(false);
alert('Stop is next');
}}>
Change to Stop
</button>
<h1 style={{color: 'darkgreen'}}>
Walk
</h1>
复制代码
因此,单击“Change to Stop”会将 walk
设置为 false
的渲染进行排队,并 alert “Stop is next”。