作者 | Gabriel Abud
譯者 | 王強
策劃 | 小智
本文最初發布於 DEV 網站,經原作者授權由 InfoQ 中文站翻譯並分享。
Redux 是 React 生態系統中的革命性技術。它使我們能夠在全局範圍記憶體儲不可變數據,並解決了在組件樹中 prop-drilling 的問題。需要在應用程序之間共享不可變數據時,它現在依舊是一種可以方便擴展的優秀工具。
但是,為什麽我們非得需要一個全局存儲呢?我們的前端應用程序真的那麽複雜嗎,還是說我們試圖用 Redux 做的事情太多了?
單頁應用程序的問題
React 這樣的單頁應用程序(SPA)的出現為我們開發 Web 應用程序的方式帶來了許多變化。它將我們的後端與前端代碼分離開來,使我們能夠專心一致並分離出關注點。圍繞狀態,它還引入了很多複雜性。
現在,異步獲取數據意味著數據必須位於兩個位置:前端和後端。我們必須考慮如何在全局範圍內以最佳方式存儲這些數據,以便它們能對我們的所有組件都可用,同時保持數據緩存以減少網絡延遲。現在,前端開發中的很大一部分負擔來自於我們的全局存儲的維護工作,我們還要確保這些存儲不會遭受狀態錯誤、數據非規範化和陳舊數據的困擾。
Redux 不是緩存
使用 Redux 和類似的狀態管理庫時,大多數人都會遇到的一大問題是,我們會將其視為後端狀態的緩存。我們獲取數據,通過 reducer/action 將其添加到存儲中,並定期重新獲取以確保它是最新的。我們用 Redux 做的事情太多了,甚至把它看成是解決問題的全面解決方案。
關鍵在於,我們的前端和後端狀態永遠不會真正同步,我們最多可以營造一種它們同步的錯覺。這是客戶端 - 伺服器模型的缺點之一,也是為什麽我們需要緩存的原因所在。但是,同步緩存和保持狀態是非常複雜的,因此我們不應該像 Redux 鼓勵的那樣,從頭開始重新創建這個後端狀態。
當我們開始在前端重新創建數據庫時,後端和前端之間的職責界限很快就變得模糊不清。作為前端開發人員,我們不需要完全了解表及其關係即可創建簡單的 UI。我們也不必知道如何高水準地標準化我們的數據。這種責任應該落在設計表的那些人(後端開發人員)身上。然後,後端開發人員可以用文檔化的 API 形式為前端開發人員提供抽象。
現在,人們圍繞 Redux 構建了無數的庫(redux-observable、redux-saga 和 redux-thunk 等),以幫助我們管理後端數據,每個庫都為已經繁瑣不已的庫又增加了一層複雜性。我相信其中大多數都沒有達成目標。有時為了前進。我們需要先退後一步。
如果我們不再在前端代碼中管理後端狀態,而只是將其視為需要定期更新的緩存會怎麽樣呢?將前端視為從緩存讀取內容的簡單顯示層後,我們的代碼就會變得更加易用,並且更適合純前端開發人員閱讀。我們獲得了分離關注點的所有好處,同時避開了構建 SPA 的大部分缺點。
後端狀態的更簡單方法
我認為有兩個庫比使用 Redux(或類似的狀態管理庫)存儲後端狀態要好用很多。
React Query
我已經在自己的多數個人和工作項目中使用 React Query 幾個月了。這個庫有一個非常簡單的 API 和幾個 hooks,用於管理查詢(獲取數據)和突變(更改數據)。
自從使用 React Query 之後,我不僅提升了效率,而且最終編寫的樣板代碼比 Redux 少了 9 成。我發現自己更容易將注意力集中在前端應用程序的 UI/UX 上,不會再時刻操心整個後端狀態了。
要對比這個庫和 Redux 的話,我們來看這兩種方法的一個代碼示例。我使用常規 JS、React Hooks 和 axios 實現了一個從伺服器獲取的簡單 TODO 列表。
首先是 Redux 實現:
請注意,到這裡甚至還沒有開始處理重新獲取、緩存和無效化,只是加載數據並在加載時將其存儲在全局存儲中而已。
下面是使用 React Query 實現的相同示例:
默認情況下,上面的示例包括具有合理默認值的數據重新獲取、緩存和過時內容無效化。你可以在全局級別設置緩存配置,然後就可以忘掉它了——一般來說它足以完成你期望的工作。有關其幕後工作機制的更多信息,請通過下方鏈接查看 React Query 文檔。它有大量的配置選項可用,本文只是介紹了一點皮毛。
https://react-query.tanstack.com/docs/overview
現在,無論需要什麽數據,你都可以將 useQuery hook 與你設置的唯一鍵(在本例中為“todos”)一起使用,並使用異步調用來獲取數據。只要函數是異步的,實現就無關緊要——你可以輕鬆地使用 Fetch API 代替 Axios。
要更改後端狀態時,React Query 提供了 useMutation hook。
https://react-query.tanstack.com/docs/guides/mutations
我還寫了一份精選的 React Query 資源列表,你可以在這裡瀏覽。
https://github.com/Buuntu/awesome-react-query
SWR
SWR 在概念上與 React Query 幾乎一致。React Query 和 SWR 大約是在同一時間開始開發的,並且以積極的方式相互影響。在 react-query 文檔中也對這兩個庫進行了徹底的比較。
與 React Query 一樣,SWR 也有真正可讀的文檔。
https://swr.vercel.app/
在大多數情況下,選擇任何一個庫都沒什麽問題。不管它們誰會在不久的將來成為事實規範,從它們中重構都要比 Redux 那堆亂麻要簡單許多。
Apollo Client
SWR 和 React Query 專注於 REST API,但如果你在 GraphQL 上需要類似的東西,就可以考慮 Apollo Client。令人欣慰的是,它的語法與 React Query 幾乎完全一樣。
前端狀態呢
一旦你開始使用這些庫,就會發現在絕大多數項目中 Redux 都太笨重了。處理完應用程序的數據獲取 / 緩存部分後,前端幾乎沒有全局狀態可處理。可以使用 Context 或 useContext+useReducer 處理剩下的少量內容,代替 Redux 的作用。
或者更好的方法是,使用 React 的內置狀態作為你的簡單前端狀態,這樣做肯定沒問題的。
我們應該更徹底地分離後端與前端,而不是陷在這種模棱兩可的中間狀態裡。本文提到的這些庫代表了我們在單頁應用程序中管理狀態的方式變革,並且是朝著正確方向邁出的一大步。我期待著看到它們能對 React 社區產生怎樣的影響。
參考閱讀:
https://dev.to/g_abud/why-i-quit-redux-1knl
InfoQ 寫作平台歡迎所有熱愛技術、熱愛創作、熱愛分享的內容創作者入駐!
還有更多超值活動等你來!