新聞中心
當聊到React狀態(tài)管理方案,很多人第一反應是Redux。

站在用戶的角度思考問題,與客戶深入溝通,找到延川網(wǎng)站設計與延川網(wǎng)站推廣的解決方案,憑借多年的經驗,讓設計與互聯(lián)網(wǎng)技術結合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站設計、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、國際域名空間、網(wǎng)絡空間、企業(yè)郵箱。業(yè)務覆蓋延川地區(qū)。
Redux為什么這么有名,個人觀點,2個原因:
出現(xiàn)時間早,當時社區(qū)還沒有更好的狀態(tài)管理解決方案
有React核心團隊光環(huán)加持。Redux的作者「Dan」開發(fā)初版Redux后便加入React團隊。另一位聯(lián)合作者「Andrew」也來自React核心團隊
Dan
合適的出現(xiàn)時機加上大名氣,催生Redux相關生態(tài)在社區(qū)快速發(fā)展,成為很多前端團隊標配。
當談論狀態(tài)管理時,通常在談什么
當談論「狀態(tài)管理」時,一般會從「廣度」、「深度」兩個方面來。
廣度上,在其之后涌現(xiàn)的解決方案,似乎都在對標Redux,提出自己獨到的解決方案。比如:
- 對標Redux的單向數(shù)據(jù)流,Mobx使用雙向數(shù)據(jù)綁定
- 對標Redux的「全局狀態(tài)」理念,recoil提出「原子狀態(tài)」理念
深度上,Redux社區(qū)不斷拓展,涌現(xiàn)了基于Redux的中間件,比如Redux-Saga。
在中間件之上,又涌現(xiàn)了更全面的解決方案,比如基于Redux-Saga的DVA。
除了這兩個緯度,還有其他視角么?
其實,我們可以從問題的本質出發(fā)。
前端,需要哪些狀態(tài)?
從頁面交互角度看,狀態(tài)來源分為兩種:
- IO操作緩存的數(shù)據(jù)
- 用戶交互的中間狀態(tài)
IO操作緩存的數(shù)據(jù)
前端最常見的IO操作是從服務端請求數(shù)據(jù)。
如果沒使用「狀態(tài)管理」方案,常見方式是請求數(shù)據(jù)后保存在組件state中,如:
- function App() {
- const [data, updateData] = useState(null);
- useEffect(() => {
- fetchData('/api/user').then(data => updateData(data))
- }, [])
- // 處理data
- }
當使用「狀態(tài)管理」方案如Redux,會將請求的數(shù)據(jù)序列化后保存在「全局狀態(tài)」中。
用戶交互的中間狀態(tài)
交互的中間狀態(tài),比如isLoading、isOpen,同樣保存在組件內部。
當是可復用組件、或狀態(tài)需要跨組件層級傳遞,通常使用Context API。
再大范圍的狀態(tài)會使用「狀態(tài)管理」方案。
可以看到,不管對于「IO操作緩存的數(shù)據(jù)」還是「用戶交互的中間狀態(tài)」,常規(guī)方案是:一視同仁。
這就又回到了討論「廣度」(使用哪種狀態(tài))與「深度」(多深入的使用這種狀態(tài)管理方案)。
但事實上,這兩種狀態(tài)的特性是不同的。
處理緩存的狀態(tài)管理
對于第一種情況,不管是服務端請求、localStorage、indexedDB,本質上說,都可以歸類為緩存。
所以,相比Redux等常規(guī)狀態(tài)管理方案,緩存處理方案可能更合適。
對于緩存,常見的需求是:
- 數(shù)據(jù)狀態(tài),加載中?加載完成?發(fā)生錯誤?
- 緩存失效后的更新
- 復用緩存數(shù)據(jù)
在React技術棧,SWR、react-query都是優(yōu)秀的解決方案。這里以SWR舉例:
對于剛才的例子:
- function App() {
- const [data, updateData] = useState(null);
- useEffect(() => {
- fetchData('/api/user').then(data => updateData(data))
- }, [])
- // 處理data
- }
SWR使用一個useSWR解決:
- function App() {
- const { data, error } = useSWR('/api/user', fetcher)
- if (error) return
failed to load- if (!data) return
loading...- return
hello {data.name}!- }
讓我們來看SWR如何滿足如上三個需求:
- 數(shù)據(jù)狀態(tài):通過useSWR的返回值參數(shù)判斷請求狀態(tài)。比如!error && !data代表「請求中」。
- 緩存失效后的更新:SWR本身是stale-while-revalidate縮寫,一種基于RFC 5861[1]的緩存更新策略。
- 復用緩存數(shù)據(jù):SWR會以請求url為key,請求對應promise為value緩存數(shù)據(jù),達到多個重復請求復用緩存的目的。
處理用戶交互的狀態(tài)管理
對于「用戶交互」產生的狀態(tài)管理需求,比如:全局modal的開關狀態(tài),頁面皮膚切換。
我們可以按項目類型、復雜度選擇合適的狀態(tài)管理方案。
橫向來看,不同類型項目適合不同狀態(tài)管理:
- 前端邏輯很重的工具類項目(比如富文本編輯器),需要完備的redo、ondo邏輯,Redux的「單向不可變數(shù)據(jù)流」是不二的選擇。
- 后臺管理系統(tǒng),邏輯不復雜,但是繁瑣。則Mobx的「雙向數(shù)據(jù)綁定」開發(fā)效率可能更高。
縱向來看,我們需要考量項目的復雜度:
類似官網(wǎng)、邏輯不復雜的SPA、個人項目,「完全沒必要」使用額外的狀態(tài)管理方案。原生Context API是你最佳的選擇。
需要小團隊合作的項目,復雜度不高的情況下,Context API就能滿足全部需要,只不過需要一點點寫法上的規(guī)范約束團隊同學。這時候可以選擇Unstated[2]
- Unstated核心代碼只有40行,為項目帶來規(guī)范的狀態(tài)管理約束的同時不會引入額外的學習成本
只有對于更復雜的項目,才應該考慮Redux、Mobx這類解決方案。
總結
對于「狀態(tài)管理」方案的選擇,我們可以遵循如下原則選擇:
區(qū)分「緩存」與「用戶交互」對應的狀態(tài),區(qū)別對待
對于「用戶交互」的狀態(tài),根據(jù)項目類型、復雜度選擇合適方案
Redux雖好,可不要濫用哦~
參考資料
[1]RFC 5861:https://tools.ietf.org/html/rfc5861
[2]Unstated:https://github.com/jamiebuilds/unstated
當前名稱:探討:Redux這么有名,只是我們不合適
本文鏈接:http://www.dlmjj.cn/article/djoseii.html


咨詢
建站咨詢
