这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战
翻译自:beta.reactjs.org/learn/state…
state 变量可能看起来像您可以读取和写入的常规 JavaScript 变量。但是,state 的行为更像是快照。设置它不会更改您已有的 state 变量,而是会触发重新渲染。
这个系列的文章你将学习到:
- 如何设置 state 的触发器进行重新 render
- state 何时以及如何更新
- 设置 state 后为什么状态不会立即更新
- 事件处理程序如何访问 state 的“快照”
系列文章
state 随时间的变化
来看一些有趣的问题,试着猜一下点击按钮会提示什么:
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 5);
alert(number);
}}>+5</button>
</>
)
}
如果使用之前的方法,您可以猜测出 alert 显示为“0”:
setNumber(0 + 5);
alert(0);
但是如果你把一个计时器放在 alert 上,让它只在组件重新渲染后触发呢?它会说“0”还是“5”?猜一猜吧!
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 5);
setTimeout(() => {
alert(number);
}, 3000);
}}>+5</button>
</>
)
}
惊讶吗?如果替换方法中的变量,可以看到传递给 alert 的是 state 的“快照”!
setNumber(0 + 5);
setTimeout(() => {
alert(0);
}, 3000);
React 中存储的 state 可能在 alert 的运行时已更改,但它使用的是用户与其交互时的 state 快照!
state 变量的值在 render 中永远不会改变,即使它的事件处理程序的代码是异步的。在 render 的 onClick 中,即使在 setNumber(number + 5) 被调用之后,number 的值仍然是 0。当 React 通过调用您的组件“获取 UI 的快照”时,它的值是“固定的”。
下面是一个示例,说明如何使你的事件处理程序更不容易出现计时错误。下面是一个发送消息延迟五秒的表单。想象一下这个场景:
- 你按下“Send”按钮,向 Alice 发送“Hello”。
- 在五秒延迟结束之前,您将“To”字段的值更改为“Bob”。
您希望显示什么?它会显示“You said Hello to Alice”吗?或者它会显示“You said Hello to Bob”?根据您所知道的进行猜测,然后尝试:
import { useState } from 'react';
export default function Form() {
const [to, setTo] = useState('Alice');
const [message, setMessage] = useState('Hello');
function handleSubmit(e) {
e.preventDefault();
setTimeout(() => {
alert(`You said ${message} to ${to}`);
}, 5000);
}
return (
<form onSubmit={handleSubmit}>
<label>
To:{' '}
<select
value={to}
onChange={e => setTo(e.target.value)}>
<option value="Alice">Alice</option>
<option value="Bob">Bob</option>
</select>
</label>
<textarea
placeholder="Message"
value={message}
onChange={e => setMessage(e.target.value)}
/>
<button type="submit">Send</button>
</form>
);
}
React 在一个渲染的事件处理程序中保持 state 值“固定”。在代码运行时,您不需要担心 state 是否发生了变化。
但是,如果您想在重新渲染之前读取最新状态怎么办?您将需要使用状态更新程序功能,可以在这里找到答案~