mobx-react-lite + Context 使用不完全指南

mobx-react-lite + Context 使用不完全指南

mobx-react-litemobx-react 的輕量版,增加了對函數式組件 hooks 的支持

隨着 React Hooks 的推出,讓我們在不編寫 class 的情況下使用 state 以及其他的 React 特性,現在項目中使用Hooks的函數式組件日益增多,而多個組件之間的狀態管理變得日益複雜。

那麼在多層級的函數式組件中如何維護好 state 呢?

React Hooks 自帶的 useReducer 配合 Context 進行狀態管理

使用過Redux的就會非常熟悉了,useReducer 可以看成Redux的簡版,使用過程中需要通過 ContextuseReducer 返回的 state dispatch 傳遞下去,子孫組件通過 useContext 獲取到 state dispatch,通過 dispatch 修改狀態,使得組件更新

這種方式針對一些沒有複雜狀態的層級組件 和 熟悉 Redux 的同學比較友好,而針對複雜的表單狀態管理和大量異步操作的層級組件顯得有點力不從心。

mobx-react-lite 配合 Context 進行狀態管理

習慣 mobx 風格進行狀態管理的開發者會更傾向於這一種,不管是複雜狀態的管理還是異步操作都支持的很好。

下文主要結合 mobxmobx-react-liteContext 進行示例描述。(我要貼代碼了)

  1. 創建 store
// store/index.js
import { observable, action, computed } from 'mobx'

export class CounterStore {
  @observable
  count = 0

  @action
  increment() {
    this.count++
  }

  @action
  decrement() {
    this.count--
  }

  @computed
  get doubleCount() {
    return this.count * 2
  }
}

export class ThemeStore {
  @observable
  theme = 'light'

  @action
  setTheme(newTheme) {
    this.theme = newTheme
  }
}

這一步創建了兩個 store 並導出

  1. 創建 Context
// contexts/index.js
import React from 'react';
import { CounterStore, ThemeStore } from '../store';

export const StoresContext = React.createContext({
  counterStore: new CounterStore(),
  themeStore: new ThemeStore()
})

創建 StoresContext 並導出,那麼後代組件在 useContext 時便可以得到包含 CounterStore ThemeStore 實例的對象

  1. 由於多組件都需要使用 useContext,我們將其封裝爲 hook 函數
// hooks/useStores.js
import React from 'react'
import { StoresContext } from '../contexts'

export const useStores = () => React.useContext(StoresContext)

通過 useStores 獲取 React.createContext 給的初始值對象(前提是沒有 StoresContext.Provider 組件,如果使用了該組件,則拿到的是 StoresContext.Providervalue 屬性對應的值)

  1. 後代組件獲取 store 並調用 action 修改狀態,使用 mobx-react-lite 更新組件
import React from 'react';
import { useStores } from '../../hooks/user-store';
import { useObserver } from 'mobx-react-lite';

const Counter = () => {
  let store = useStores(); // 獲取store

  const {counterStore, themeStore} = store;

  const handleIncrement = () => {
    counterStore.increment();
  }
  const handleDecrement = () => {
    counterStore.decrement();
  }

  return useObserver(() => (
    <div>
      <p>count: {counterStore.count}</p>
      <p>theme: {themeStore.theme}</p>
      <button onClick={handleIncrement}>add</button>
      <button onClick={handleDecrement}>dec</button>
    </div>
  ))
}

export default Counter;

通過 useStores 獲取state進行展示,調用 action 修改 store 狀態,會被 useObserver 監聽到,並更新組件

總結

這裏只用到 mobx-react-lite 中的 useObserver API,其他的常用 API 還有 useLocalStore observer 等,文檔在 mobx-react

Using MobX with React Hooks and TypeScript
這篇文章做了詳細實例,其中使用了 useLocalStore observer 並配合 Typescript 做了優化

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