不要再問React Hooks能否取代 Redux 了
許多同事一直問我一些類似的問題:
“如果我們在專案中使用hooks,我們是否還需要Redux?”
“React Hooks會不會使Redux太過時了?我能不能用Hooks來做所有Redux能做的事呢?”
在Google中搜索會發現,大家經常問這些問題。
“React Hooks是否會取代Redux?”,最簡單的回答是“不一定”。
更細緻但禮貌的答案是“嗯,那取決於你正在做的專案型別”。
我更傾向於告訴大家的答案是“我不確定你是否知道你在說什麼”。有幾個原因可以說明,為什麼“React Hooks是否會取代Redux”是一個本質上有缺陷的問題。首先:
Redux一直是非強制性的
通過Dan Abramov(Redux的創造者之一)的一篇文章【You Might Not Need Redux】可以看出,如果你不需要使用它,則無需替換任何東西。
Redux是一個JavaScript庫,並且如果你用的是React(另一個JavaScript庫),那麼為了使用Redux,你還需要在應用中載入一個React-Redux的JavaScript庫。在專案中使用依賴庫會增加打包體積,這會增加你應用的載入時間。基於這個原因,你不應該使用一些庫,像jQuery、Redux、MobX(另一個狀態管理庫),甚至是React,除非你有明確的理由要使用它們。
當大家問到“是否hooks會替代Redux”,他們似乎經常覺得,他們的React應用需要使用其中一種。事實並非如此,如果你正在寫的應用沒有很多狀態需要被儲存,或者你的元件結構很簡單,可以避免過度的prop傳遞,以及基於React本身提供的特性,你的狀態已經足夠可控了,不管有沒有hooks,這些情況使用狀態管理就沒有多大意義了。
即使你確實有許多的狀態,或者有像老樹根一樣扭曲分叉的React元件結構,你仍然不需要狀態管理庫。Prop傳遞可能很麻煩,但是React給了你許多狀態管理選項,並且hooks絕對可以幫你很好地組織狀態。Redux是一個輕量級的庫,但是它的設定很複雜,增加了打包體積,並且很多地方需要權衡。有很多原因可以說明,為什麼你應該選擇不在專案中使用它,並且這些原因很有說服力。
你並不總是需要Redux,這也是在說,你依然有許多理由去使用它的。如果你的專案在一開始就使用了Redux,那麼它可能是一個很好的理由,無論它是否做了這些:組織(應用狀態的可預測性、單一的資料流,在複雜的應用中很有用)、中介軟體、Redux的強有力的開發工具和除錯能力。如果你有使用Redux的理由,它不會因為React Hooks變得無效。如果你之前需要Redux,那麼你現在仍然需要。這是因為:
React Hooks和Redux並沒有試圖解決同樣的問題
Redux是一個狀態管理庫,Hooks是React最近更新的部分特性,讓你的函式元件可以做類元件能做的事情。
所以不使用類元件來寫React應用突然會讓狀態管理庫變得過時了呢?
當然不會!
通過檔案可以看出,React Hooks被開發出來主要是這三個理由:
難以複用類元件之間的邏輯
生命週期中經常包含一些莫名其妙的不相關邏輯
類元件難以被機器和人理解
注意,沒有一條理由的動機直接表明要做一些與狀態管理相關的事情。
話說如此,React Hooks確實提供了一些選擇去管理應用的狀態。尤其是useState、useReducer和useContext方法,提供來新的方式去維護你的狀態,這被證明比先前React提供的選項更好、更有條理。
但是這些hooks並不是什麼新東西或神奇的東西,並且它們也沒有使狀態管理過時,因為事實是:
React Hooks並沒有讓你的應用可以做一些以前做不到的事情
那就對了,你現在可以寫函式元件來做一些以前只能用類元件來做的事情,但是這些函式元件並不能做一些類元件做不到的事情,除了可以更好地組織和複用程式碼的能力。它們不一定讓你的應用更好,而是讓開發者的體驗更好。
useState和useReducer只是管理元件狀態的方法,並且它們的工作原理同類元件的this.state和this.setState是一樣的,你仍然需要傳遞你的props。
useContext是大家認為在Redux板上釘釘的特性,因為它可以讓你在元件之間共享應用的狀態,而不需要通過prop傳遞,但是它也沒有真正的做任何新的事情。context API現在是React的一部分,useContext僅僅是讓你不用包裹也可以使用context。並且有一些開發這用context來管理整個應用的狀態,這不是設計context的目的。通過檔案可以看出:
Context is designed to share data that can be considered “global” for a tree of React components,such as the current authenticated user,theme,or preferred language. Context是為了共享資料而被設計出來的,可以認為是React元件樹的“全域性”,比如當前已授權的使用者、主題或者首選的語言。
換句話說,就是那些預計不會頻繁更新的東西。
檔案中也建議有節制地使用context,因為“它會使得元件難以複用”。他們也提醒開發者,如果開發者不小心,context很容易觸發不必要的重複渲染。
我見過專案成功地使用React Context來管理應用狀態,這是有可能的,也不失為一種選擇。但是狀態管理並不完全是context被設計出來去做的事情,而且Redux和其他狀態管理庫被設計出來就是為了處理這種特定的目的。
此外,React Hooks也絕不意味著Redux的消亡,因為如果你看一眼React-Redux最近更新的檔案,你會明白:
React-Redux也有自己的hooks
沒錯,React Hooks正在幫助React-Redux恢復活力並移除來它的一些痛點,與“替代”的說法相差甚遠。
我在另一篇文章中對React-Redux進行了深入研究,這裡要說的重點。在hooks之前,你必須定義mapStateToProps和mapDispatchToProps兩個函式,並且用connect包裹你的元件來建立一個高階元件,它會傳遞dispatch方法和部分Redux貯存的狀態,這些狀態是你在mapping函式中指定作為props傳遞到元件中的。
讓我們來看一個非常簡單的計數器應用的例子(太簡單甚至都不需要Redux,但是這裡主要是為了展示一些資訊)。假設我們已經定義了Redux store和increment、decrement兩個action creator(完整的原始碼在這裡)。
太令人煩惱了!如果我們不必包裹元件到高階元件中,就可以讓元件取到Redux store的值,這樣不是更友好嗎?是的,這就是hooks出現的原因。Hooks就是為了複用程式碼和消除由於高階元件產生的“巢狀地獄”。下面是一個相同的元件,使用React-Redux hooks轉換成函式元件。
是不是很漂亮?簡而言之,useSelector讓你可以儲存部分Redux store的值到你的元件。useDispatch更簡單,它僅僅為你提供了一個dispatch函式,你可以用它來傳送狀態更新到Redux store。最棒的是,你不再需要寫這些醜陋的mapping函式和用connect函式來包裹元件。現在,一切都很好地包含在你的元件中,它更簡潔,因此更容易閱讀,並且更有條理。重點是:
沒有必要比較React Hooks和Redux孰優孰劣
毫無疑問,這兩項技術可以很好地互補。React Hooks不會替代Redux,它們僅僅為你提供來新的、更好的方式去組織你的React應用。如果你最終決定使用Redux來管理狀態,可以讓你編寫更好的連線元件。
所以,請不要再問“React Hooks是否會取代Redux?”。
相反,開始問自己“我正在製作什麼樣的應用?我需要什麼樣的狀態管理?Redux可以用嗎,還是有些過度使用呢?hooks可以用嗎,還是應該用類元件?如果我決定使用Redux和React Hooks(或者MobX和React Hooks,或者Redux和jQuery,不用React——這些都是有效的選擇,取決於你正在做的事情),那麼我怎樣可以使這些技術互補並且和諧共處呢?”。
原文連結:英文:Max González 譯文:連城
zhuanlan.zhihu.com/p/81126574