Skip to content

Commit ab2adaf

Browse files
committed
fix(learn): 屬性 -> prop/props
1 parent c621ed5 commit ab2adaf

1 file changed

Lines changed: 24 additions & 24 deletions

File tree

src/content/learn/lifecycle-of-reactive-effects.md

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: '響應式 Effect 的生命週期'
44

55
<Intro>
66

7-
Effect 和元件的生命週期並不相同。元件會掛載(mount)、更新或卸載(unmount)。Effect 只能做兩件事:開始同步某件事,並在稍後結束同步。如果你的 Effect 依賴隨著時間改變屬性(props及狀態,這個循環可以發生很多次。React 有提供一個 linter 規範來檢查是否已經正確指定 Effect 的依賴項目。這能讓你的 Effect 與最新的屬性和狀態保持同步
7+
Effect 和元件的生命週期並不相同。元件會掛載(mount)、更新或卸載(unmount)。Effect 只能做兩件事:開始同步某件事,並在稍後結束同步。如果你的 Effect 依賴隨著時間改變 props 及狀態,這個循環可以發生很多次。React 有提供一個 linter 規範來檢查是否已經正確指定 Effect 的依賴項目。這能讓你的 Effect 與最新的 props 和狀態保持同步
88

99
</Intro>
1010

@@ -26,10 +26,10 @@ Effect 和元件的生命週期並不相同。元件會掛載(mount)、更
2626
每個 React 的元件都會經歷同樣的生命週期:
2727

2828
- _掛載_:元件被新增到畫面中。
29-
- _更新_元件接收新的屬性或狀態,通常是在回應一個互動。
29+
- _更新_元件接收新的 props 或狀態,通常是在回應一個互動。
3030
- _卸載_:元件從畫面中被移除。
3131

32-
**這是一個思考元件的好方法,但不適用於 Effect。** 應該試著將每個 Effect 獨立於元件來思考。Effect 是用來描述如何以當前的屬性及狀態[同步一個外部系統](/learn/synchronizing-with-effects)。隨著程式碼改變,同步的頻率會增加或減少。
32+
**這是一個思考元件的好方法,但不適用於 Effect。** 應該試著將每個 Effect 獨立於元件來思考。Effect 是用來描述如何以當前的 props 及狀態[同步一個外部系統](/learn/synchronizing-with-effects)。隨著程式碼改變,同步的頻率會增加或減少。
3333

3434
為了說明這一點,來看看一個將元件連線到聊天伺服器的 Effect:
3535

@@ -84,7 +84,7 @@ Effect 的主體(body)指定如何 **開始同步**:
8484

8585
### 為什麼可能需要同步不止一次 {/*why-synchronization-may-need-to-happen-more-than-once*/}
8686

87-
想像一下 `ChatRoom` 元件接收一個 `roomId` 屬性,是使用者在下拉式選單選取的值。一開始使用者選了 `"general"` 作為 `roomId`。你的應用程式會顯示 `"general"` 這個聊天室:
87+
想像一下 `ChatRoom` 元件接收一個 `roomId` prop,是使用者在下拉式選單選取的值。一開始使用者選了 `"general"` 作為 `roomId`。你的應用程式會顯示 `"general"` 這個聊天室:
8888

8989
```js {3}
9090
const serverUrl = 'https://localhost:1234';
@@ -120,18 +120,18 @@ function ChatRoom({ roomId /* "travel" */ }) {
120120
}
121121
```
122122
123-
想想看接下來應該會發生什麼事。使用者在 UI 中看到 `"travel"` 聊天室被選取,但上一次執行的 Effect 還是連線到 `"general"` 房間。**因為 `roomId` 屬性已經改變了,所以後續你的 Effect (與 `"general"` 聊天室連線)與 UI 並不相符**。
123+
想想看接下來應該會發生什麼事。使用者在 UI 中看到 `"travel"` 聊天室被選取,但上一次執行的 Effect 還是連線到 `"general"` 房間。**因為 `roomId` prop 已經改變了,所以後續你的 Effect (與 `"general"` 聊天室連線)與 UI 並不相符**。
124124
125125
基於這點,你會希望 React 能做兩件事:
126126
127127
1. 停止以舊的 `roomId` 同步(從 `"general"` 聊天室中斷連線)
128128
2. 開始以新的 `roomId` 同步(連線到 `"travel"` 聊天室)
129129
130-
**幸運的是,你已經告訴 React 要怎麼做這兩件事!**Effect 的主體指定如何開始同步,而清除函式則是指定如何停止同步。React 必須做的就只是以正確的順序,並使用正確的屬性和狀態來呼叫它們。讓我們來看看到底是怎麼發生的。
130+
**幸運的是,你已經告訴 React 要怎麼做這兩件事!**Effect 的主體指定如何開始同步,而清除函式則是指定如何停止同步。React 必須做的就只是以正確的順序,並使用正確的 props 和狀態來呼叫它們。讓我們來看看到底是怎麼發生的。
131131
132132
### React 如何重新同步你的 Effect {/*how-react-re-synchronizes-your-effect*/}
133133
134-
回想一下 `ChatRoom` 元件已經從 `roomId` 屬性接收了新的值。這個值原本是 `"general"`,現在則是 `"travel"`。React 需要重新同步 Effect,以重新連線到不同的房間。
134+
回想一下 `ChatRoom` 元件已經從 `roomId` prop 接收了新的值。這個值原本是 `"general"`,現在則是 `"travel"`。React 需要重新同步 Effect,以重新連線到不同的房間。
135135
136136
為了 **停止同步**,React 會在連線到 `"general"` 聊天室後,呼叫 Effect 回傳的清除函式。因為 `roomId``"general"`,清除函式會從 `"general"` 聊天室中斷連線:
137137
@@ -158,7 +158,7 @@ function ChatRoom({ roomId /* "travel" */ }) {
158158
159159
多虧這樣,你現在連到和使用者在 UI 中所選相同的房間。災難解除!
160160
161-
每次元件以不同的 `roomId` 重渲染(re-render)之後,Effect 就會重新同步。舉例來說,使用者把 `roomId``"travel"` 改成 `"music"`。React 會再次以清除函式 **停止同步** Effect(從 `"travel"` 聊天室中斷連線)。接著 React 會執行 Effect 的主體,以新的 `roomId` 屬性再次 **開始同步**(讓你連線到 `"music"` 聊天室)。
161+
每次元件以不同的 `roomId` 重渲染(re-render)之後,Effect 就會重新同步。舉例來說,使用者把 `roomId``"travel"` 改成 `"music"`。React 會再次以清除函式 **停止同步** Effect(從 `"travel"` 聊天室中斷連線)。接著 React 會執行 Effect 的主體,以新的 `roomId` prop 再次 **開始同步**(讓你連線到 `"music"` 聊天室)。
162162
163163
最後,當使用者去到不同的畫面,`ChatRoom` 卸載。現在完全沒必要保持連線了。React 會最後一次 **停止同步** 你的 Effect,並中斷你和 `"music"` 聊天室的連線。
164164
@@ -291,7 +291,7 @@ button { margin-left: 10px; }
291291
你可能在想 React 是怎麼知道 Effect 在 `roomId` 改變後,需要重新同步。這是因為 *你告訴 React* 它的程式碼依賴 `roomId`,藉由[依賴的清單](/learn/synchronizing-with-effects#step-2-specify-the-effect-dependencies):
292292

293293
```js {1,3,8}
294-
function ChatRoom({ roomId }) { // roomId 屬性可能隨著時間改變
294+
function ChatRoom({ roomId }) { // roomId prop 可能隨著時間改變
295295
useEffect(() => {
296296
const connection = createConnection(serverUrl, roomId); // Effect 讀取 roomId
297297
connection.connect();
@@ -304,7 +304,7 @@ function ChatRoom({ roomId }) { // roomId 屬性可能隨著時間改變
304304

305305
運作方式如下:
306306

307-
1. 你知道 `roomId` 是一個屬性,這意味著它會隨著時間改變
307+
1. 你知道 `roomId` 是一個 prop,這意味著它會隨著時間改變
308308
2. 你知道你的 Effect 讀取 `roomId`(所以它的邏輯依賴稍後可能會改變的值)。
309309
3. 這就是為什麼你指定 `roomId` 作為你的 Effect 的依賴(以至於 Effect 會在 `roomId` 改變時重新同步)。
310310

@@ -373,21 +373,21 @@ function ChatRoom({ roomId }) {
373373

374374
這是因為 `serverUrl` 完全不會因為重渲染而改變。不管元件重渲染多少次,`serverUrl` 都是一樣的。因為 `serverUrl` 不會改變,沒道理將它指定為依賴。畢竟,依賴只會在隨著時間改變時做一些事!
375375

376-
另一方面,`roomId` 在重渲染時可能不同。**屬性、狀態和元件中其它被宣告的值是 _響應式的_,因為它們是在渲染時被計算,而且參與了 React 的資料流。**
376+
另一方面,`roomId` 在重渲染時可能不同。**props、狀態和元件中其它被宣告的值是 _響應式的_,因為它們是在渲染時被計算,而且參與了 React 的資料流。**
377377

378378
如果 `serverUrl` 是一個狀態變數(state variable),它就會是響應式的。響應式的值必須包含在依賴中:
379379

380380
```js {2,5,10}
381-
function ChatRoom({ roomId }) { // 屬性隨著時間改變
381+
function ChatRoom({ roomId }) { // props 隨著時間改變
382382
const [serverUrl, setServerUrl] = useState('https://localhost:1234'); // 狀態可能隨著時間改變
383383
384384
useEffect(() => {
385-
const connection = createConnection(serverUrl, roomId); // Effect 讀取屬性和狀態
385+
const connection = createConnection(serverUrl, roomId); // Effect 讀取 props 和狀態
386386
connection.connect();
387387
return () => {
388388
connection.disconnect();
389389
};
390-
}, [roomId, serverUrl]); // 所以你告訴 React,Effect「依賴」屬性和狀態
390+
}, [roomId, serverUrl]); // 所以你告訴 React,Effect「依賴」props 和狀態
391391
// ...
392392
}
393393
```
@@ -551,9 +551,9 @@ button { margin-left: 10px; }
551551

552552
### 元件主體中所有宣告的變數都是響應式的 {/*all-variables-declared-in-the-component-body-are-reactive*/}
553553

554-
屬性和狀態不是唯一的響應式數值,以這兩者計算而來的值也是響應式的。當屬性和狀態改變,元件會重渲染,計算而來的值也會跟著改變。這也是為什麼元件主體中,被 Effect 用到的所有數值都應該包含在依賴的清單中。
554+
Props 和狀態不是唯一的響應式數值,以這兩者計算而來的值也是響應式的。當 props 和狀態改變,元件會重渲染,計算而來的值也會跟著改變。這也是為什麼元件主體中,被 Effect 用到的所有數值都應該包含在依賴的清單中。
555555

556-
使用者能從下拉式選單選擇一個聊天伺服器,但他們也可以在設置中設定一個預設伺服器。假設你已經將這些設定的狀態放進一個 [Context](/learn/scaling-up-with-reducer-and-context),所以你能從 Context 讀取 `settings`現在你需要根據屬性中所選的伺服器和預設伺服器,來計算 `serverUrl`
556+
使用者能從下拉式選單選擇一個聊天伺服器,但他們也可以在設置中設定一個預設伺服器。假設你已經將這些設定的狀態放進一個 [Context](/learn/scaling-up-with-reducer-and-context),所以你能從 Context 讀取 `settings`現在你需要根據 props 中所選的伺服器和預設伺服器,來計算 `serverUrl`
557557

558558
```js {3,5,10}
559559
function ChatRoom({ roomId, selectedServerUrl }) { // roomId 是響應式的
@@ -570,9 +570,9 @@ function ChatRoom({ roomId, selectedServerUrl }) { // roomId 是響應式的
570570
}
571571
```
572572

573-
在這個範例中,`serverUrl` 不是屬性,也不是狀態變數。它只是渲染期間計算而來的普通的值。但因為它是渲染期間所計算,所以可能因為重渲染而改變。這也就是為什麼它是響應式的。
573+
在這個範例中,`serverUrl` 不是 prop,也不是狀態變數。它只是渲染期間計算而來的普通的值。但因為它是渲染期間所計算,所以可能因為重渲染而改變。這也就是為什麼它是響應式的。
574574

575-
**元件中的所有值(包含屬性、狀態和元件主體中的變數)都是響應式的。任何響應式的值在重渲染中都可以改變,所以必須將響應式的值包含在 Effect 的依賴中。**
575+
**元件中的所有值(包含 props、狀態和元件主體中的變數)都是響應式的。任何響應式的值在重渲染中都可以改變,所以必須將響應式的值包含在 Effect 的依賴中。**
576576

577577
換句話說,Effect 會對元件主體中所有的值做出「反應(react)」。
578578

@@ -737,7 +737,7 @@ function ChatRoom() {
737737

738738
* **確認你的 Effect 在獨立的同步程序中所代表的意義。** 如果你的 Effect 沒有同步任何東西,[它可能就是不必要的](/learn/you-might-not-need-an-effect)。如果你的 Effect 同步許多獨立的東西,[應該把它們拆分](#each-effect-represents-a-separate-synchronization-process)。
739739

740-
* **如果你想要讀取屬性或狀態最新的值,但不「響應」這些值,也不重新同步 Effect,** 你可以將 Effect 拆分成響應式的部分(你保留在 Effect 中的部分)和非響應式的部分(你會抽出的部分,被稱為 _Effect 事件_)。[閱讀更多關於把事件從 Effect 中分離](/learn/separating-events-from-effects)。
740+
* **如果你想要讀取 props 或狀態最新的值,但不「響應」這些值,也不重新同步 Effect,** 你可以將 Effect 拆分成響應式的部分(你保留在 Effect 中的部分)和非響應式的部分(你會抽出的部分,被稱為 _Effect 事件_)。[閱讀更多關於把事件從 Effect 中分離](/learn/separating-events-from-effects)。
741741

742742
* **避免將物件和函式作為依賴。** 如果你在渲染期間創建物件和函式,接著在 Effect 中讀取它們,它們在每次渲染時都會不同。這會導致 Effect 每次都會重新同步。[閱讀更多關於把不必要的依賴從 Effect 中移除](/learn/removing-effect-dependencies)。
743743

@@ -859,7 +859,7 @@ button { margin-left: 10px; }
859859

860860
<Solution>
861861

862-
這個 Effect 根本沒有依賴陣列,所以會在每次重渲染時重新同步。首先,新增一個依賴陣列。接下來,確保 Effect 所用到的每個響應式數值都被指定在陣列中。舉例來說,`roomId` 是響應式的(因為它是一個屬性),所以應該包含在陣列中。這確保使用者選取不同的房間時,都會重新連線到聊天室。另一方面,`serverUrl` 是在元件外定義的,這就是為什麼它不需要在陣列裡。
862+
這個 Effect 根本沒有依賴陣列,所以會在每次重渲染時重新同步。首先,新增一個依賴陣列。接下來,確保 Effect 所用到的每個響應式數值都被指定在陣列中。舉例來說,`roomId` 是響應式的(因為它是一個 prop),所以應該包含在陣列中。這確保使用者選取不同的房間時,都會重新連線到聊天室。另一方面,`serverUrl` 是在元件外定義的,這就是為什麼它不需要在陣列裡。
863863

864864
<Sandpack>
865865

@@ -1316,7 +1316,7 @@ body {
13161316

13171317
#### 修正連線開關 {/*fix-a-connection-switch*/}
13181318

1319-
在這個範例中,`chat.js` 中的聊天服務提供兩個不同的 API`createEncryptedConnection``createUnencryptedConnection``App` 根元件讓使用者選擇是否使用加密機制,接著向下傳遞(pass down)對應的 API 方法給 `ChatRoom` 子元件作為 `createConnection` 屬性
1319+
在這個範例中,`chat.js` 中的聊天服務提供兩個不同的 API`createEncryptedConnection``createUnencryptedConnection``App` 根元件讓使用者選擇是否使用加密機制,接著向下傳遞(pass down)對應的 API 方法給 `ChatRoom` 子元件作為 `createConnection` prop
13201320

13211321
注意一開始 console log 說連線沒有加密。試著勾選核取方塊:沒有任何事情發生。但是,如果你在那之後更改所選的房間,那聊天室會重新連線 *並且* 開啟加密機制(就跟你在 console 訊息裡看到的一樣)。這是一個 bug。修正這個 bug,讓切換核取方塊 ** 能使聊天室重新連線。
13221322

@@ -1422,7 +1422,7 @@ label { display: block; margin-bottom: 10px; }
14221422

14231423
<Solution>
14241424

1425-
如果移除掉 linter 的抑制,就會看到一個 lint 錯誤。問題出在 `createConnection` 是屬性,因此它是響應式數值。它會隨著時間改變!(確實,它應該改變——像是使用者點選核取方塊時,父元件傳入不同的值給 `createConnection` 屬性。)這就是為什麼它應該是依賴。將它納入依賴清單來修正這個 bug:
1425+
如果移除掉 linter 的抑制,就會看到一個 lint 錯誤。問題出在 `createConnection` 是 prop,因此它是響應式數值。它會隨著時間改變!(確實,它應該改變——像是使用者點選核取方塊時,父元件傳入不同的值給 `createConnection` prop。)這就是為什麼它應該是依賴。將它納入依賴清單來修正這個 bug:
14261426

14271427
<Sandpack>
14281428

@@ -1517,7 +1517,7 @@ label { display: block; margin-bottom: 10px; }
15171517

15181518
</Sandpack>
15191519

1520-
`createConnection` 是依賴,這是正確的。不過這段程式碼有點脆弱,因為有些人可能會將行內函式(inline function作為屬性的值傳給 `App` 元件。在此情況下,每次 `App` 元件重渲染時,這個值就會不同,Effect 可能會因此太常重新同步。為了避免這個情況,你可以向下傳遞 `isEncrypted` 作為代替:
1520+
`createConnection` 是依賴,這是正確的。不過這段程式碼有點脆弱,因為有些人可能會將行內函式(inline function作為 prop 的值傳給 `App` 元件。在此情況下,每次 `App` 元件重渲染時,這個值就會不同,Effect 可能會因此太常重新同步。為了避免這個情況,你可以向下傳遞 `isEncrypted` 作為代替:
15211521

15221522
<Sandpack>
15231523

@@ -1612,7 +1612,7 @@ label { display: block; margin-bottom: 10px; }
16121612
16131613
</Sandpack>
16141614
1615-
在這個版本中,`App` 元件傳入布林屬性,而不是函式。在 Effect 中,你來決定用哪個函式。`createEncryptedConnection``createUnencryptedConnection` 都是在元件外宣告,因此不是響應式,也不需要是依賴。你將會在[移除 Effect 的依賴](/learn/removing-effect-dependencies)的章節學到更多相關資訊。
1615+
在這個版本中,`App` 元件傳入布林 prop,而不是函式。在 Effect 中,你來決定用哪個函式。`createEncryptedConnection``createUnencryptedConnection` 都是在元件外宣告,因此不是響應式,也不需要是依賴。你將會在[移除 Effect 的依賴](/learn/removing-effect-dependencies)的章節學到更多相關資訊。
16161616
16171617
</Solution>
16181618

0 commit comments

Comments
 (0)