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

React Hooks比你想象的更強大。css

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

Hooks基礎

若是你已經很熟悉React Hooks,那麼能夠直接跳過這部分。github

useState()npm

在Hooks以前,功能組件沒有狀態。如今,使用useState(),咱們可讓功能組件擁有狀態。編程


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

useEffect()數組

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

默認狀況下,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

相關文章
相關標籤/搜索