Skip to content

Commit 71ca462

Browse files
Merge pull request #388 from Annie-Chien/docs/state-as-a-snapshot
2 parents 37ce585 + 3707d5f commit 71ca462

File tree

1 file changed

+68
-68
lines changed

1 file changed

+68
-68
lines changed

Diff for: src/content/learn/state-as-a-snapshot.md

+68-68
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
---
2-
title: State as a Snapshot
2+
title: 如同快照的 State
33
---
44

55
<Intro>
66

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.
7+
State 變數或許和可讀寫的普通 JavaScript 變數看起來很像。然而,state 的行為更像是一張快照(snapshot)。設定 state 並不會改變你已有的 state 變數,而是會觸發重新 render
88

99
</Intro>
1010

1111
<YouWillLearn>
1212

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
13+
* 設定 state 是如何觸發重新 render
14+
* state 更新的時機和方式
15+
* state 在設定後並未立即更新的原因
16+
* event handler 是如何取得 state 的「快照」
1717

1818
</YouWillLearn>
1919

20-
## Setting state triggers renders {/*setting-state-triggers-renders*/}
20+
## 設定 state 會觸發 render {/*setting-state-triggers-renders*/}
2121

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*.
22+
你可能會認為使用者介面會直接對點擊等使用者事件做出改變以作為回應。在 React 裡,它的運作方式和這種思維模型有點不同。在前一章,你看過來自 React[設定 state 來請求重新 render](/learn/render-and-commit#step-1-trigger-a-render)。這意味著介面若要為特定的事件做出回應,則需要*更新 state*
2323

24-
In this example, when you press "send", `setIsSent(true)` tells React to re-render the UI:
24+
在此範例中,當你點擊「傳送」,`setIsSent(true)` 會通知 React 重新 render UI:
2525

2626
<Sandpack>
2727

@@ -61,43 +61,43 @@ label, textarea { margin-bottom: 10px; display: block; }
6161

6262
</Sandpack>
6363

64-
Here's what happens when you click the button:
64+
以下是當你點擊按鈕時所發生的事情:
6565

66-
1. The `onSubmit` event handler executes.
67-
2. `setIsSent(true)` sets `isSent` to `true` and queues a new render.
68-
3. React re-renders the component according to the new `isSent` value.
66+
1. 執行 `onSubmit` event handler
67+
2. `setIsSent(true)` `isSent` 設定為 `true`,並安排新的一次 render
68+
3. React 根據 `isSent` 新的值,重新 render component。
6969

70-
Let's take a closer look at the relationship between state and rendering.
70+
接著就讓我們來仔細看看 state rendering 之間的關係吧!
7171

72-
## Rendering takes a snapshot in time {/*rendering-takes-a-snapshot-in-time*/}
72+
## Rendering 會即時生成一張快照 {/*rendering-takes-a-snapshot-in-time*/}
7373

74-
["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.**
74+
[Rendering](/learn/render-and-commit#step-2-react-renders-your-components)意味著 React 正在呼叫你的 component,它其實就是一個函式。函式回傳的 JSX 就像是一張 UI 的即時快照。它的 propsevent handler 和區域變數都是**利用當下 render 的 state** 計算出來的。
7575

76-
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 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.
76+
與照片或電影畫面不同的是,你所回傳的 UI「快照」是具有互動性的。它包含了像是 event handler 的邏輯,明確說明要如何針對輸入做出回應。React 會更新畫面以符合這張快照,並連結 event handler。因此,按下按鈕將會觸發 JSX 裡的 click handler
7777

78-
When React re-renders a component:
78+
React 重新 render component 時:
7979

80-
1. React calls your function again.
81-
2. Your function returns a new JSX snapshot.
82-
3. React then updates the screen to match the snapshot you've returned.
80+
1. React 再次呼叫函式。
81+
2. 函式回傳一張全新的 JSX 快照。
82+
3. 接著,React 更新畫面,使畫面與你回傳的快照相符。
8383

8484
<IllustrationBlock sequential>
8585
<Illustration caption="React executing the function" src="/images/docs/illustrations/i_render1.png" />
8686
<Illustration caption="Calculating the snapshot" src="/images/docs/illustrations/i_render2.png" />
8787
<Illustration caption="Updating the DOM tree" src="/images/docs/illustrations/i_render3.png" />
8888
</IllustrationBlock>
8989

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!**
90+
State 是 component 的記憶,它和那種函式回傳後就消失的一般變數不同。State 其實「存在於」React 本身 - 如同放在架子上!- 在函式之外。當 React 呼叫 component,它會是你特定 render 的 state 快照。Component 回傳的 UI 快照內的 JSX 裡有最新的 props event handler,全都是**使用那一次 render 的 state **所計算出來的。
9191

9292
<IllustrationBlock sequential>
9393
<Illustration caption="You tell React to update the state" src="/images/docs/illustrations/i_state-snapshot1.png" />
9494
<Illustration caption="React updates the state value" src="/images/docs/illustrations/i_state-snapshot2.png" />
9595
<Illustration caption="React passes a snapshot of the state value into the component" src="/images/docs/illustrations/i_state-snapshot3.png" />
9696
</IllustrationBlock>
9797

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.
98+
以下是一個簡單範例,用來呈現其運作方式。在此範例中,你可能會預期點擊「+3」按鈕將遞增計數器三次,因為它呼叫了三次 `setNumber(number + 1)`
9999

100-
See what happens when you click the "+3" button:
100+
看看當你點擊「+3」按鈕會發生什麼事:
101101

102102
<Sandpack>
103103

@@ -127,9 +127,9 @@ h1 { display: inline-block; margin: 10px; width: 30px; text-align: center; }
127127

128128
</Sandpack>
129129

130-
Notice that `number` only increments once per click!
130+
注意,`number` 在每次點擊只會遞增一次!
131131

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:
132+
**設定 state 只會為*下一次* render 改變 state。** 在第一次 render 中,`number` `0`。這是為什麼在*該次 render* onClick handler 中,即便在呼叫了 `setnumber(number + 1)`後, `number` 的值仍然為 `0` 的原因:
133133

134134
```js
135135
<button onClick={() => {
@@ -139,18 +139,18 @@ Notice that `number` only increments once per click!
139139
}}>+3</button>
140140
```
141141

142-
Here is what this button's click handler tells React to do:
142+
以下是這個按鈕的 click handler 通知 React 要做的事:
143143

144-
1. `setNumber(number + 1)`: `number` is `0` so `setNumber(0 + 1)`.
145-
- React prepares to change `number` to `1` on the next render.
146-
2. `setNumber(number + 1)`: `number` is `0` so `setNumber(0 + 1)`.
147-
- React prepares to change `number` to `1` on the next render.
148-
3. `setNumber(number + 1)`: `number` is `0` so `setNumber(0 + 1)`.
149-
- React prepares to change `number` to `1` on the next render.
144+
1. `setNumber(number + 1)`: `number` `0`,因此 `setNumber(0 + 1)`
145+
- React 準備在下一次 render 將 `number` 更改為 `1`
146+
2. `setNumber(number + 1)`: `number` `0`,因此 `setNumber(0 + 1)`
147+
- React 準備在下一次 render 將 `number` 更改為 `1`
148+
3. `setNumber(number + 1)`: `number` `0`,因此 `setNumber(0 + 1)`
149+
- React 準備在下一次 render 將 `number` 更改為 `1`
150150

151-
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`.
151+
雖然呼叫了 `setNumber(number + 1)` 三次,在*這一次 render* event handler 內的 `number` 一直都是 `0`,所以等同於你把 state 設定為 `1` 三次。這就是為什麼在 event handler 執行結束後,React 用等於 `1` 而非 `3``number` 來重新 render component。
152152

153-
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:
153+
你也可以透過在心裡將程式碼中的 state 變數替換為它們的值來視覺化這一切。由於在*這一次 render* 中,state 變數 `number` 的值為 `0`,它的 event handler 看起來就像是這樣:
154154

155155
```js
156156
<button onClick={() => {
@@ -160,7 +160,7 @@ You can also visualize this by mentally substituting state variables with their
160160
}}>+3</button>
161161
```
162162

163-
For the next render, `number` is `1`, so *that render's* click handler looks like this:
163+
對下一次的 render 來說,`number` `1`,因此*該次 render* click handler 看起來就像是這樣:
164164

165165
```js
166166
<button onClick={() => {
@@ -170,11 +170,11 @@ For the next render, `number` is `1`, so *that render's* click handler looks lik
170170
}}>+3</button>
171171
```
172172

173-
This is why clicking the button again will set the counter to `2`, then to `3` on the next click, and so on.
173+
這就是為什麼再次點擊按鈕會將計數器設定為 `2`,然後在下一次點擊時會設定為 `3`,依此類推。
174174

175-
## State over time {/*state-over-time*/}
175+
## 隨著時間改變的 state {/*state-over-time*/}
176176

177-
Well, that was fun. Try to guess what clicking this button will alert:
177+
嗯,那真是有趣。試著猜猜看點擊這個按鈕會彈出什麼提示框:
178178

179179
<Sandpack>
180180

@@ -203,14 +203,14 @@ h1 { display: inline-block; margin: 10px; width: 30px; text-align: center; }
203203

204204
</Sandpack>
205205

206-
If you use the substitution method from before, you can guess that the alert shows "0":
206+
如果你使用之前提到的替換法,你可以猜到提示框會顯示「0」:
207207

208208
```js
209209
setNumber(0 + 5);
210210
alert(0);
211211
```
212212

213-
But what if you put a timer on the alert, so it only fires _after_ the component re-rendered? Would it say "0" or "5"? Have a guess!
213+
但要是你在提示框上設定計時器,使其在 component 重新 render _之後_ 才觸發呢?那麼它會顯示「5」還是「0」?猜猜看!
214214

215215
<Sandpack>
216216

@@ -241,7 +241,7 @@ h1 { display: inline-block; margin: 10px; width: 30px; text-align: center; }
241241

242242
</Sandpack>
243243

244-
Surprised? If you use the substitution method, you can see the "snapshot" of the state passed to the alert.
244+
驚不驚訝?如果你使用替換法,你就可以看到傳入提示框的 state「快照」。
245245

246246
```js
247247
setNumber(0 + 5);
@@ -250,16 +250,16 @@ setTimeout(() => {
250250
}, 3000);
251251
```
252252

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!
253+
儲存在 React 裡的 state 在提示框執行時可能已改變,但它是用使用者與其互動當下的 state 快照來安排的!
254254

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.
255+
**在同一次 render 裡,state 變數的值永遠不會改變**,就算它的 event handler 的程式碼是非同步的。在*該次 render* `onClick` 內,即使在呼叫 `setNumber(number + 5)`之後,`number` 的值仍然為 `0`。當 React 透過呼叫 component 來替 UI「拍攝快照」時,state 的值「固定不變」。
256256

257-
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:
257+
以下是一個範例,說明這如何使 event handler 不容易出現時序錯誤。下面是一個表單,延遲五秒後會發送一則訊息。想像一下以下的情況:
258258

259-
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".
259+
1. 你按下「傳送」按鈕,向 Alice 傳送「Hi」。
260+
2. 在五秒的延遲結束之前,你將「To」欄位的值更改為「Bob」。
261261

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:
262+
你預期 `alert` 顯示什麼?它會顯示「You said Hello to Alice」還是「You said Hello to Bob」?根據所學猜一猜並試試看:
263263

264264
<Sandpack>
265265

@@ -305,29 +305,29 @@ label, textarea { margin-bottom: 10px; display: block; }
305305

306306
</Sandpack>
307307

308-
**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.
308+
**React 會使 state 值在同一次 render 內的 event handler 保持「固定不變」。** 你不需要擔心 state 在程式碼執行時有所異動。
309309

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!
310+
但要是你希望在重新 render 之前讀取最新的 state 呢?你將會需要使用 [state 的更新函式](/learn/queueing-a-series-of-state-updates),這會下一章節中介紹!
311311

312312
<Recap>
313313

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.
314+
* 設定 state 會請求一次新的 render
315+
* React state 儲存在 component 外,好比在架子上一樣。
316+
* 當你呼叫 `useState`React *為該次 render* 拍一張 state 的快照。
317+
* 變數和 event handler 不會在重新 render 時「存活」。每次 render 都有自己的 event handler。
318+
* 每次 render(和其內部的函式)始終會「看到」React *該次* render 所提供的 state 快照。
319+
* 你可以在內心替换 event handler 中的 state,類似於替換被 render 的 JSX
320+
* 過去建立的 event handler 保有它們被建立的那一次 render 中的 state 值。
321321

322322
</Recap>
323323

324324

325325

326326
<Challenges>
327327

328-
#### Implement a traffic light {/*implement-a-traffic-light*/}
328+
#### 實作紅綠燈 {/*implement-a-traffic-light*/}
329329

330-
Here is a crosswalk light component that toggles when the button is pressed:
330+
以下是一個紅綠燈 component,按按鈕可以切換它的狀態:
331331

332332
<Sandpack>
333333

@@ -362,13 +362,13 @@ h1 { margin-top: 20px; }
362362

363363
</Sandpack>
364364

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".
365+
請在 click handler 裡加入一個 `alert`。當燈是綠色的並顯示「Walk」時,點擊按鈕應顯示「Stop is next」。當燈是紅色的並顯示「Stop」時,點擊按鈕應顯示「Walk is next」。
366366

367-
Does it make a difference whether you put the `alert` before or after the `setWalk` call?
367+
無論你將 `alert` 放在呼叫 `setWalk` 之前還是之後,是否會有不同呢?
368368

369369
<Solution>
370370

371-
Your `alert` should look like this:
371+
`alert` 看起來應該像這樣:
372372

373373
<Sandpack>
374374

@@ -404,17 +404,17 @@ h1 { margin-top: 20px; }
404404

405405
</Sandpack>
406406

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.
407+
無論你把它放在呼叫 `setWalk` 之前或之後都是一樣的。該次 render`walk` 值是固定的。呼叫 `setWalk` 只會在*下一次* render 中改變它,但不會影響前一次 render 中的 event handler
408408

409-
This line might seem counter-intuitive at first:
409+
這一行程式碼乍看之下可能會令人感到困惑:
410410

411411
```js
412412
alert(walk ? 'Stop is next' : 'Walk is next');
413413
```
414414

415-
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.
415+
但如果你這樣解讀它就變得合理了:「如果紅綠燈顯示『Walk now』,那麼訊息應該顯示『Stop is next』」。在 event handler 中的 `walk` 變數與該次 render`walk` 值相符,且不會改變。
416416

417-
You can verify that this is correct by applying the substitution method. When `walk` is `true`, you get:
417+
你可以透過應用替換法來驗證這是正確的。當 `walk` `true` 時,你可以得到:
418418

419419
```js
420420
<button onClick={() => {
@@ -428,8 +428,8 @@ You can verify that this is correct by applying the substitution method. When `w
428428
</h1>
429429
```
430430

431-
So clicking "Change to Stop" queues a render with `walk` set to `false`, and alerts "Stop is next".
431+
因此,點擊「Change to Stop」時,會安排一次把 `walk` 設定為 `false` 的 render,並跳出「Stop is next」的提示框。
432432

433433
</Solution>
434434

435-
</Challenges>
435+
</Challenges>

0 commit comments

Comments
 (0)