使用React Hooks進行狀態管理 - 無Redux和Context API

React Hooks比你想象的更強大。

現在,我們將探索和開發一個自定義Hook來管理全局狀態 - 比Redux更容易使用的方法,並且比Context API更高效。

Hooks基礎

如果你已經很熟悉React Hooks,那麼可以直接跳過這部分。

useState()

在Hooks之前,功能組件沒有狀態。現在,使用useState(),我們可以讓功能組件擁有狀態。


useState()會返回一個數組。上面數組的第一項是一個可以訪問狀態值的變量。第二項是一個能夠更新組件狀態,而且影響dom變化的函數。

useEffect()

類似Component組件,使用生命週期方法來管理副作用,例如componentDidMount()。useEffect() 函數允許您在函數組件中執行副作用。

默認情況下,useEffect在每次完成渲染後運行。但是,您可以選擇僅在某些值發生更改時觸發它,並將一個數組作爲第二個可選參數傳遞。

要獲得與 componentDidMount() 相同的結果,我們可以發送一個空數組。空數組不會改變,useEffect只會運行一次。

共享states

我們可以看到Hooks狀態與類組件狀態完全相同。組件的每個實例都有自己的狀態。

爲了組件之間共享狀態,我們將創建一個自定義Hook。


這個想法是創建一個監聽器數組,只有一個狀態對象。每當一個組件更改狀態時,所有訂閱的組件都會觸發其 setState() 函數並進行更新。

我們可以通過調用自定義Hook中的 useState() 來實現。我們將 setState() 函數添加到一個監聽器數組,並返回一個函數用來更新state 和 運行所有監聽器函數。

現在已經有了 use-global-hook 這個npm包,您可以通過包文檔中的示例瞭解如何使用它。但是,從現在開始,我們將專注於它是怎麼實現的。

第一個版本


在組件中使用它:


第一個版本已經可以共享狀態。您可以在應用程序中添加任意數量的Counter組件,它們都具有相同的全局狀態。

但我們可以做得更好

我想在第一個版本中改進的內容:

  • 我想在卸載組件時從數組中刪除監聽器。

  • 我想讓它更通用,可以在其他項目中使用。

  • 我想通過參數設置 initialState。

  • 我想使用更多函數式編程。

在組件卸載之前調用一個函數

我們瞭解到,使用空數組調用 useEffect(function,[])與componentDidMount() 具有相同的用途。但是,如果第一個參數中使用的函數返回另一個函數,則第二個函數將在卸載組件之前觸發。完全像 componentWillUnmount()。

這是從監聽器數組中刪除組件的理想位置。

第二個版本

除了最後的修改,我們還將:

  • 將React設置爲參數,不再導入它。

  • 不導出 customHook,而是導出根據 initialState 參數返回新 customHook()。

  • 創建一個包含state和 setState() 函數的store對象。

  • 替換 setState() 和 useCustom() 的上下文爲store。

因爲我們現在有一個更通用的Hook,我們必須在store文件中設置它。

將actions與組件分開

如果您曾經使用過複雜的狀態管理庫,那麼您就知道直接在組件中操作全局狀態並不是最好的做法。

最好的方法是,通過創建操作狀態的action來分離業務邏輯。出於這個原因,我希望我們的解決方案的最後一個版本中,組件不能訪問setState()去操作狀態,而是通過actions。

爲了解決這個問題,我們的 useGlobalHook(React,initialState,actions) 函數將接收一個action對象作爲第三個參數。關於這一點,我想補充一些東西:

Actions將有權訪問store對象。因此,action可以使用 store.state 讀取狀態,通過store.setState() 寫入狀態,甚至使用 state.actions 調用其他操作。

對於組織,actions對象可以包含其他actions的子對象。因此,您可能調用 actions.addToCounter(amount) ,**或者一個action子對象, 調用actions.counter.add(amount) **。

最終版本

以下是NPM包use-global-hook中的內容。

最後,一個實戰案例

src/styles.css

src/index.js

src/store/index.js

src/components/Counters.js

src/components/Repos.js

src/components/SearchForm.js

src/actions/counter.js

src/actions/github.js

src/actions/index.js

package.json

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章