在昨天的篇章,介紹了詳細的 state 變化流程。今天則是要來介紹在使用 state 的時候,我們該如何選擇他的架構該長什麼樣子。昨天已經有先提到一些了,今天會再做更詳細的介紹。
今天的文章參考官方文件的:
要設計好一個 React 應用程式,好的 state 架構十分重要。好的架構可以幫助減少非預期錯誤,更好的可讀性,讓開發者寫得更順暢。官方文件提供幾個方法可以參考:
今天就會根據這五項進行詳細的介紹。
有時候剛開始設計 state 架構的時候,我們可能會不確定會使用到多少個 state。文章就用座標當例子:
const [x, setX] = useState(0);
const [y, setY] = useState(0);
或是
const [position, setPosition] = useState({ x: 0, y: 0 });
這兩個方法都可以使用,但如果我們很常同時改 x
跟 y
的話,就變成需要總是寫上 setX
跟 setY
,有時候就會不小心漏掉一個導致程式錯誤。所以當我們在開發的時候,發現有哪些 state 是經常需要一起更新的,就可以把它們組合在一起變成一個 state 來利用。
在把 state 組合起來的時候,要特別小心我們在更新的時候不能一次只改裡面其中一個項目:
// 錯誤!會把 Position 改成只剩 x
setPosition({ x: 100 })
// 正確!沒動到的 y 會被保留
setPosition({ ...position, x: 100 })
這在昨天的文章有提到,在設計 state 的時候,可能會遇到像是 isTyping
跟 isSubmitting
同時是 true
的情況發生,但我們的 UI 不應該要有這種情況。這種很常在使用很多 Boolean 的 state 的時候產生,因為兩種 boolean 就要考量四種不同可能。這時候我們可以使用一個 status
state 去管理狀態,就不會造成混淆。
當我們可以用其他 state 去推算出想要的資料,就不需要特別再使用 state 去管理。像是文章中的名字當例子,我們有 firstName
跟 lastName
並且想顯示組合在一起的 fullName
。由於 fullName
是由 firstName
跟 lastName
組成,就不用特別再用 state 去存,然後在修改的時候去 setFullName
,直接寫成 const fullName = firstName + ' ' + lastName
就好。
這也常用在一些公式計算,像是我們知道打擊率是 安打 / 打數
,那我們要顯示打擊率就不用特別再多寫個 state 去管理他。
有時候我們會需要透過 state 去更改當下選取的資料一個陣列裡的資料,第一個想到的方法就是在使用兩個 state 去管理,一個是存資料陣列 items
,跟儲存選取資料的 selectedItem
,然後在選取的時候去更新 selectedItem
,並且用這個選取的資料去顯示我們要的畫面。但這會發生一個問題,當我們同時也想更新原本的 items
資料的時候,剛好更新到我們當下選取的 item
,如果沒同時更新 selectedItem
,我們畫面想呈現的內容可能就不會一起更新到。
要避免這樣的問題,我們可以把 selectedItem
改成只去存相關資料的 id
,並且在每次 render 的時候透過 find()
這個方法去獲得選取資料:
const [items, setItems] = useState(initialItems)
const [selectedId, setSelectedId] = useState(initialItems[0].id)
const selectedItem = items.find(item => item.id === selectedId)
這樣不管 items
怎麼改裡面的內容,selectedItem
都能抓到剛好更新完的資料,因為他是透過改完的 items
來獲得的。這樣的設計方式就可以只保留到重要的 state,而把重複資料避免掉。
之前就要提到,巢狀的 state 不管是更新或刪除都會十分複雜,讓我們開發處理的複雜度提高,所以我們在設計架構的時候會想要盡量避免這種情況發生。假設資料真的就是如此,官方文件也提供幾種方法讓我們參考:
childIds
去管理。透過扁平化的處理,我們在更新 state 的時候就不用一層一層慢慢查找,而是只需要知道需要修改的資料 id
就好了。props
的傳遞,讓資料在不同的 components 裡處理,這樣就能把 state 的複雜度降低。關於 State 架構,今天的介紹告一個段落,希望大家還好理解。在設計 state 的時候要考慮的面向很多,但我覺得一開始先盡量把想得到先宣告出來,之後再慢慢合併與刪減也沒關係,有時候就是需要累積點經驗,才能設計出最有效的 state。所以大家也不用太擔心一開始的 state 有沒有寫好,多試試看就知道,只是記得照著前面介紹的方法,來檢視自己的 state 設計是否還有更好的改良空間。
今天的文章就到這邊,感謝大家耐心地看完,如果有任何問題與建議歡迎告訴我,明天見,晚安。