我的許多同事最近通過各種方式問同一類問題:
“如果我們開始用 hook 后,那還有必要用 Redux 嗎?”
“react hook 不是讓 Redux 過時了嗎?那只用 Hooks 就可以做 Redux 所有能做的事了吧?”
隨便搜一下 Google,你就會發現人們也在互聯網上問同樣的問題。簡單來說,“react Hooks 是否替代了 Redux”這個問題的答案是:“不”。更細致不過禮貌的答案是:“嗯,這個取決於你實際項目的類型“。最終,我傾向於回答人們“我不確定你是否明白自己在說什么”。“React Hooks 取代了 Redux”這個論點有着根本的缺陷,其原因有好幾個。首先:
Redux 從始至終都是可選方案
Redux 的作者之一 Dan Abramov 曾經表達過 你可能不需要 Redux 的建議。如果你本來就不需要某樣東西,那你也就不用替換它了。
如果你正在用 React,為了用起來 Redux,你還得把 Redux-Redux 裝到你的應用里。在項目中使用多個庫顯然會增加最終應用打包的大小,也就會增加加載應用所需的時間。因此,除非有真正的理由,你不應該使用任何庫,如 jQuery,Redux,MobX,甚至是 React。
當人們問起來 hook 是否能替代 Redux 時,他們似乎認為得在這兩者之間做出選擇,但事實並非如此。如果你正開發的應用不需要存儲大量狀態,或者組件層次足夠簡單不需要深層次的 prop 傳遞,那么用整個狀態管理庫方案是沒有意義的。無論是否使用 hook,應用的狀態都足夠由 React 提供的功能進行管理了。
即便你的應用需要管理一個龐大的狀態,或者應用的層次結構如古樹的根一樣錯綜復雜,你也不一定非得使用狀態管理庫。深層次傳遞 prop 可能很麻煩,但原生的 React 已經為你提供了包含在 hook 在內的多種狀態管理的選擇,他們都能幫你把狀態管理的井井有條。Redux 是一個輕量級的庫,不過配置相對復雜,增加最終打包的體積,還需要做出各種權衡取舍。不在項目中使用 Redux 有許多合理的理由,所以你並不總是需要用它。
雖然如此,我們還是有許多理由使用 Redux。如果你的項目本來就在用 Redux,那最開始決定使用 Redux 應該是有一些好的理由的,比如項目的組織架構需要有一個可預測的,單一事實來源的程序狀態;中間件功能;或是強大的開發調試工具。如果你曾有理由使用 Redux,那 hook 並不會讓你的這些理由失效。如果你曾需要用 Redux,那你也許還得繼續用它。
React hook 嘗試解決問題與 Redux 不同
Redux 是一個狀態管理庫。Hooks 是最近才加入 React 的新功能,它可以讓函數組件支持曾經只在 class 組件中支持的特性。
那么,用函數組件替換 class 組件實現 React 應用會讓狀態管理庫過時嗎?答案是否定的。
關於為何開發 React hook, 官方文檔 給出了三個主要原因:
-
class 組件的邏輯復用很困難。
-
生命周期方法內常包含讓人困惑的無關邏輯。
-
class 對於機器和人類來說都難以理解。
你可以注意到這些動機都跟狀態管理無關。
話雖如此,React hook 確實為你提供了狀態管理的新選擇。值得注意的是,useState,useReducer 和 useContext 這些管理狀態的新方法,一定程度上比之前 React 原生提供的方案更好、更有條理。但 React hook 沒有提供超出之前 React 版本的新能力,也不會讓狀態管理庫過時。
React hook 不會使 React 應用做任何它以前做不到的事
沒錯,函數組件可以做到以前只有在 class 組件才能實現的功能,同時函數組件有更好的代碼組織結構和重用能力,但函數組件做不到 class 組件也做不到的事。React hook 的目的不是為了讓應用更好,而是為了讓開發體驗更好。
useState 和 useReducer 只是管理組件狀態的方法,其工作方式與 class 組件中的 this.state 和 this.setState 工作方式的大致相同。對於深層傳遞 prop 的問題,hook 也是無能為力。
人們似乎認為 useContext 可以把 Redux 打入冷宮,因為你可以使用它解決狀態深層次傳遞的問題,但它確實不是什么新功能。 context API 已經存在於 React 一段時間了。useContext 只是讓你可以不通過 包裝組件就能使用 context。雖然有些開發人員選擇使用 context 管理整個應用的狀態,但 context 的設計初衷不是如此。官方文檔提到:
Context 設計目的是為了共享那些對於一個組件樹而言是“全局”的數據,例如當前認證的用戶、主題或首選語言。
換句話說,放在 context 中的數據不應該經常更新。
文檔還建議要謹慎使用 context,因為“它會讓代碼復用變得更困難“。他們還警告開發人員,如果使用不當,context 還會導致不必要的重新渲染。
我見到過一些項目成功使用 React context 管理整個應用的狀態。理論上這確實是一種選擇。但 context 的設計初衷並不包含狀態管理,而這是 Redux 或是其他狀態管理庫的設計目的。
此外,React hook 絕對不意味着 Redux 的滅亡,如果你瞅一眼 React-Redux 最近更新的文檔,你會看到:
React-Redux 也擁有自己的 hook 了
沒錯,React hook 有助於重振 React-Redux 庫,並移除了一些它的痛點。這與“hook 會替代 Redux”這個觀點相去甚遠。
我在另一篇文章深入介紹了 React-Redux 中的 hook 。在引入 hook 之前,你必須定義 mapStateToProps 與 mapDispatchToProps 函數、並用 connect 函數包裝你的組件來創建出一個高階組件。該高階組件會把 dispatch 函數與 Redux store 的一部分狀態通過你定義的映射函數作為 props,傳到被 conntext 包裝的組件中。
我們來看個非常簡單的計數器應用示例(實際上因為過於太簡單不必使用 Redux,但這個例子是為了表達一下信息的概述)。假設我們已經定義了 Redux store,並在其他地方定義了增加和減少的動作創建方法。
真是繁瑣。如果我們可以不用把組件包裝在高階組件內就能讓組件訪問到 Redux store,不更好嗎?沒錯,這就是 hook 可以發揮的地方了。hook 其主要功能就是代碼復用,同時消除高階組件導致的“包裝地獄”問題。
簡而言之,useSelector 允許你將 Redux store 的各個狀態切片保存為組件的變量。useDispatch 非常簡單,你可以通過它發出動作更新 Redux store。最重要的是,你不再需要實現丑陋的映射函數,並把組件包裝在 connect 函數中了。現在,一切都很好的包含在你的組件里。這樣的實現更簡短,也就更具有可讀性、更有條理。
廣州品牌設計公司https://www.houdianzi.com PPT模板下載大全https://redbox.wode007.com
React hook 和 Redux 不是互為競爭關系的技術
顯然,這兩種技術可以相互補充。React hook 不會“替換 Redux”,它只是為你提供了更新、也許更好的方式組織你的 React 應用;如果你最終決定使用 Redux 管理應用狀態,也許能寫出更高內聚的組件。
所以,請不要再問 "React hook 是否取代了 Redux?" 的問題了。
相反,請問一下自己:“我在開發怎樣的應用?我需要怎么樣的狀態管理需求?Redux 是否對我來說是合理的方案,或者它對於我的需求過度復雜了?如果我決定使用 Redux 和 React hook(或是 MobX+Hook, Redux+jQuery 等技術組合)我怎樣才能讓這些技術相互補充,和諧工作呢?”