管理狀態
隨著應用程式的增長,更有意識地組織狀態以及資料在元件之間的流動方式會有所幫助。冗餘或重複的狀態是常見的錯誤來源。在本章中,你將學習如何良好地建構狀態、如何保持狀態更新邏輯的可維護性,以及如何在遠距離元件之間共享狀態。
使用狀態響應輸入
使用 React 時,你不會直接從程式碼修改 UI。例如,你不會編寫像「停用按鈕」、「啟用按鈕」、「顯示成功訊息」等指令。相反,你會描述元件在不同視覺狀態下(「初始狀態」、「輸入狀態」、「成功狀態」)希望看到的 UI,然後觸發狀態變更以響應使用者輸入。這類似於設計師思考 UI 的方式。
這是一個使用 React 建構的測驗表單。請注意它如何使用status 狀態變數來決定是否啟用或停用提交按鈕,以及是否顯示成功訊息。
選擇狀態結構
良好的狀態結構可以區分出一個易於修改和除錯的元件與一個持續產生錯誤的元件。最重要的原則是狀態不應包含冗餘或重複的資訊。如果存在不必要的狀態,很容易忘記更新它,從而引入錯誤!
例如,這個表單有一個冗餘的fullName狀態變數:
你可以移除它,並在元件渲染時計算 fullName 來簡化程式碼:
這可能看起來是一個小改變,但 React 應用程式中的許多錯誤都是這樣修復的。
在元件之間共享狀態
有時,你會希望兩個元件的狀態始終一起變化。為此,請將狀態從兩者中移除,將其移動到它們最近的共同父元件,然後透過 props 將其傳遞給它們。這被稱為「狀態提升」,是編寫 React 程式碼時最常做的事情之一。
在這個例子中,一次應該只有一個面板處於活動狀態。為了實現這一點,父元件持有狀態並為其子元件指定 props,而不是將活動狀態保留在每個單獨的面板內部。
保留與重置狀態
當你重新渲染一個元件時,React 需要決定樹的哪些部分要保留(並更新),哪些部分要丟棄或從頭重新建立。在大多數情況下,React 的自動行為已經足夠好用。預設情況下,React 會保留與先前渲染的元件樹「匹配」的樹的部分。
然而,有時這並非你所期望的。在這個聊天應用程式中,輸入訊息然後切換收件人並不會重置輸入框。這可能導致使用者不小心將訊息發送給錯誤的人:
React 允許您覆蓋預設行為,並強制元件透過傳遞不同的key來重置其狀態,例如<Chat key={email} />。這告訴 React,如果收件者不同,它應該被視為一個不同的Chat元件,需要從頭開始使用新資料(以及輸入框等 UI)重新建立。現在切換收件者會重置輸入欄位——即使您渲染的是同一個元件。
將狀態邏輯提取到 Reducer 中
具有許多狀態更新且分散在眾多事件處理器中的元件可能會變得難以管理。對於這些情況,您可以將所有狀態更新邏輯整合到元件外部的一個單一函式中,稱為「reducer」。您的事件處理器會變得簡潔,因為它們只需指定使用者的「動作」。在檔案底部,reducer 函式會指定狀態應如何回應每個動作進行更新!
使用 Context 深度傳遞資料
通常,你會透過 props 將資訊從父元件傳遞給子元件。但是,如果你需要將某些 prop 傳遞給許多元件,或者許多元件需要相同的資訊,那麼傳遞 props 可能會變得不方便。Context 讓父元件可以將某些資訊提供給其下方樹狀結構中的任何元件——無論深度如何——而無需透過 props 明確傳遞。
在這裡,Heading 元件透過「詢問」最近的 Section其層級來決定其標題層級。每個Section 透過詢問父級 Section並將其加一來追蹤自己的層級。每個Section都向其下方的所有元件提供資訊,而無需傳遞 props——它是透過 context 來實現的。
使用 Reducer 和 Context 擴展規模
Reducer 讓你可以整合元件的狀態更新邏輯。Context 讓你可以將資訊深度傳遞給其他元件。你可以將 reducer 和 context 結合起來,以管理複雜畫面的狀態。
透過這種方法,具有複雜狀態的父元件使用 reducer 來管理它。樹狀結構中任何深處的其他元件都可以透過 context 讀取其狀態。它們也可以 dispatch 操作來更新該狀態。
接下來呢?
前往 使用狀態響應輸入 開始逐頁閱讀本章!
或者,如果您已經熟悉這些主題,何不閱讀關於逃生艙口的內容?
