You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: beta/src/content/learn/state-as-a-snapshot.md
+77-76
Original file line number
Diff line number
Diff line change
@@ -1,27 +1,30 @@
1
1
---
2
-
title: State as a Snapshot
2
+
title: state 如同一张快照
3
+
translators:
4
+
- zzw
5
+
- Neo42
3
6
---
4
7
5
8
<Intro>
6
9
7
-
State variables might look like regular JavaScript variables that you can read and write to. However, state behaves more like a snapshot. Setting it does not change the state variable you already have, but instead triggers a re-render.
10
+
也许 state 变量看起来和一般的可读写的 JavaScript 变量类似。但 state 在其表现出的特性上更像是一张快照。设置它不会更改你已有的 state 变量,但会触发重新渲染。
8
11
9
12
</Intro>
10
13
11
14
<YouWillLearn>
12
15
13
-
*How setting state triggers re-renders
14
-
*When and how state updates
15
-
*Why state does not update immediately after you set it
16
-
*How event handlers access a "snapshot" of the state
16
+
*设置 state 如何导致重新渲染
17
+
* state 在何时以何种方式更新
18
+
*为什么 state 不在设置后立即更新
19
+
*事件处理函数如何获取 state 的一张“快照”
17
20
18
21
</YouWillLearn>
19
22
20
-
## Setting state triggers renders {/*setting-state-triggers-renders*/}
23
+
## 设置 state 会触发渲染 {/*setting-state-triggers-renders*/}
21
24
22
-
You might think of your user interface as changing directly in response to the user event like a click. In React, it works a little differently from this mental model. On the previous page, you saw that [setting state requests a re-render](/learn/render-and-commit#step-1-trigger-a-render) from React. This means that for an interface to react to the event, you need to *update the state*.
25
+
你可能会认为你的用户界面会直接对点击之类的用户输入做出响应并发生变化。在 React 中,它的工作方式与这种思维模型略有不同。在上一页中,你看到了来自 React 的[设置 state 请求重新渲染](/learn/render-and-commit#step-1-trigger-a-render)。这意味着要使界面对输入做出反应,你需要设置其 state。
23
26
24
-
In this example, when you press "send", `setIsSent(true)`tells React to re-render the UI:
["Rendering"](/learn/render-and-commit#step-2-react-renders-your-components)means that React is calling your component, which is a function. The JSX you return from that function is like a snapshot of the UI in time. Its props, event handlers, and local variables were all calculated **using its state at the time of the render.**
Unlike a photograph or a movie frame, the UI "snapshot" you return is interactive. It includes logic like event handlers that specify what happens in response to inputs. React then updates the screen to match this snapshot and connects the event handlers. As a result, pressing a button will trigger the click handler from your JSX.
<Illustration caption="更新 DOM 树" src="/images/docs/illustrations/i_render3.png" />
88
91
</IllustrationBlock>
89
92
90
-
As a component's memory, state is not like a regular variable that disappears after your function returns. State actually "lives" in React itself--as if on a shelf!--outside of your function. When React calls your component, it gives you a snapshot of the state for that particular render. Your component returns a snapshot of the UI with a fresh set of props and event handlers in its JSX, all calculated **using the state values from that render!**
93
+
作为一个组件的记忆,state 不同于在你的函数返回之后就会消失的普通变量。state 实际上“活”在 React 本身中——就像被摆在一个架子上!——位于你的函数之外。当 React 调用你的组件时,它会为特定的那一次渲染提供一张 state 快照。你的组件会在其 JSX 中返回一张包含一整套新的 props 和事件处理函数的 UI 快照 ,其中所有的值都是 **根据那一次渲染中 state 的值** 被计算出来的!
91
94
92
95
<IllustrationBlocksequential>
93
-
<Illustrationcaption="You tell React to update the state"src="/images/docs/illustrations/i_state-snapshot1.png" />
94
-
<Illustrationcaption="React updates the state value"src="/images/docs/illustrations/i_state-snapshot2.png" />
95
-
<Illustrationcaption="React passes a snapshot of the state value into the component"src="/images/docs/illustrations/i_state-snapshot3.png" />
<Illustrationcaption="React 更新 state 的值"src="/images/docs/illustrations/i_state-snapshot2.png" />
98
+
<Illustrationcaption="React 向组件内传入一张 state 的快照"src="/images/docs/illustrations/i_state-snapshot3.png" />
96
99
</IllustrationBlock>
97
100
98
-
Here's a little experiment to show you how this works. In this example, you might expect that clicking the "+3" button would increment the counter three times because it calls `setNumber(number + 1)`three times.
Notice that `number`only increments once per click!
133
+
请注意,每次点击只会让 `number`递增一次!
131
134
132
-
**Setting state only changes it for the *next* render.** During the first render, `number`was`0`. This is why, in *that render's*`onClick`handler, the value of `number` is still `0` even after `setNumber(number + 1)`was called:
135
+
**设置 state 只会为 *下一次* 渲染变更 state 的值。**在第一次渲染期间,`number`为`0`。这也就解释了为什么在 *那次渲染中的*`onClick`处理函数中,即便在调用了 `setNumber(number + 1)`之后,`number` 的值也仍然是 `0`:
133
136
134
137
```js
135
138
<button onClick={() => {
@@ -139,18 +142,18 @@ Notice that `number` only increments once per click!
139
142
}}>+3</button>
140
143
```
141
144
142
-
Here is what this button's click handler tells React to do:
Even though you called `setNumber(number + 1)` three times, in *this render's* event handler `number`is always `0`, so you set the state to`1` three times. This is why, after your event handler finishes, React re-renders the component with `number`equal to `1`rather than `3`.
You can also visualize this by mentally substituting state variables with their values in your code. Since the `number`state variable is `0` for *this render*, its event handler looks like this:
156
+
你还可以通过在心里把 state 变量替换成它们在你代码中的值来想象这个过程。由于 *这次渲染* 中的 state 变量 `number`是 `0`,其事件处理函数看起来会像这样:
154
157
155
158
```js
156
159
<button onClick={() => {
@@ -159,8 +162,7 @@ You can also visualize this by mentally substituting state variables with their
159
162
setNumber(0+1);
160
163
}}>+3</button>
161
164
```
162
-
163
-
For the next render, `number` is `1`, so *that render's* click handler looks like this:
Surprised? If you use the substitution method, you can see the "snapshot" of the state passed to the alert.
245
+
惊讶吗?你如果使用替代法,就能看到被传入提示框的 state “快照”。
245
246
246
247
```js
247
248
setNumber(0+5);
@@ -250,16 +251,16 @@ setTimeout(() => {
250
251
}, 3000);
251
252
```
252
253
253
-
The state stored in React may have changed by the time the alert runs, but it was scheduled using a snapshot of the state at the time the user interacted with it!
254
+
到提示框运行时,React 中存储的 state 可能已经发生了更改,但是这次更改是根据用户与其交互时的 state 快照来安排的!
254
255
255
-
**A state variable's value never changes within a render,**even if its event handler's code is asynchronous. Inside *that render's*`onClick`, the value of `number`continues to be `0` even after `setNumber(number + 5)`was called. Its value was "fixed" when React "took the snapshot" of the UI by calling your component.
Here is an example of how that makes your event handlers less prone to timing mistakes. Below is a form that sends a message with a five-second delay. Imagine this scenario:
1.You press the "Send" button, sending "Hello" to Alice.
260
-
2.Before the five-second delay ends, you change the value of the "To" field to "Bob".
260
+
1.你按下“发送”按钮,向 Alice 发送“你好”。
261
+
2.在五秒延迟结束之前,将“To”字段的值更改为“Bob”。
261
262
262
-
What do you expect the `alert`to display? Would it display, "You said Hello to Alice"? Or would it display, "You said Hello to Bob"? Make a guess based on what you know, and then try it:
263
+
你觉得 `alert`会显示什么?它是会显示“你向 Alice 说了你好“还是会显示“你向 Tom 说了你好”?根据你已经学到的知识猜一猜,然后动手试一试:
**React keeps the state values "fixed" within one render's event handlers.**You don't need to worry whether the state has changed while the code is running.
309
+
**React 会使 state 的值始终”固定“在一次渲染的各个事件处理函数内部。**你无需担心代码运行时 state 是否发生了变化。
309
310
310
-
But what if you wanted to read the latest state before a re-render? You'll want to use a [state updater function](/learn/queueing-a-series-of-state-updates), covered on the next page!
311
+
但是,万一你想在重新渲染之前读取最新的 state 怎么办?你应该使用 [状态更新函数](/learn/queueing-a-series-of-state-updates),下一页将会介绍!
311
312
312
313
<Recap>
313
314
314
-
*Setting state requests a new render.
315
-
* React stores state outside of your component, as if on a shelf.
316
-
*When you call `useState`, React gives you a snapshot of the state *for that render*.
317
-
*Variables and event handlers don't "survive" re-renders. Every render has its own event handlers.
318
-
*Every render (and functions inside it) will always "see" the snapshot of the state that React gave to *that* render.
319
-
*You can mentally substitute state in event handlers, similarly to how you think about the rendered JSX.
320
-
*Event handlers created in the past have the state values from the render in which they were created.
315
+
*设置 state 请求一次新的渲染。
316
+
* React 将 state 存储在组件之外,就像在架子上一样。
317
+
*当你调用 `useState` 时,React 会为你提供*该次渲染* 的一张 state 快照。
318
+
*变量和事件处理函数不会在重渲染中“存活”。每个渲染都有自己的事件处理函数。
319
+
*每个渲染(以及其中的函数)始终“看到”的是 React 提供给*这个* 渲染的 state 快照。
320
+
*你可以在心中替换事件处理函数中的 state,类似于替换渲染的 JSX。
321
+
*过去创建的事件处理函数拥有的是创建它们的那次渲染中的 state 值。
321
322
322
323
</Recap>
323
324
324
325
325
326
326
327
<Challenges>
327
328
328
-
#### Implement a traffic light {/*implement-a-traffic-light*/}
329
+
###实现红绿灯组件 {/*implement-a-traffic-light*/}
329
330
330
-
Here is a crosswalk light component that toggles on when the button is pressed:
331
+
以下是一个人行道红绿灯组件,在按下按钮时会切换状态:
331
332
332
333
<Sandpack>
333
334
@@ -362,13 +363,13 @@ h1 { margin-top: 20px; }
362
363
363
364
</Sandpack>
364
365
365
-
Add an `alert`to the click handler. When the light is green and says "Walk", clicking the button should say "Stop is next". When the light is red and says "Stop", clicking the button should say "Walk is next".
366
+
向 click 事件处理函数添加一个 `alert`。当灯为绿色且显示“Walk”时,单击按钮应显示“Stop is next”。当灯为红色并显示“Stop”时,单击按钮应显示“Walk is next”。
366
367
367
-
Does it make a difference whether you put the `alert`before or after the `setWalk`call?
368
+
把 `alert`方法放在 `setWalk`方法之前或之后有区别吗?
368
369
369
370
<Solution>
370
371
371
-
Your`alert`should look like this:
372
+
你的`alert`看起来应该像是这样:
372
373
373
374
<Sandpack>
374
375
@@ -404,17 +405,17 @@ h1 { margin-top: 20px; }
404
405
405
406
</Sandpack>
406
407
407
-
Whether you put it before or after the `setWalk`call makes no difference. That render's value of `walk`is fixed. Calling `setWalk`will only change it for the *next* render, but will not affect the event handler from the previous render.
But it makes sense if you read it as: "If the traffic light shows 'Walk now', the message should say 'Stop is next.'" The `walk`variable inside your event handler matches that render's value of `walk`and does not change.
0 commit comments