如何利用 React Hooks 管理全局狀態

如何利用 React Hooks 管理全局狀態

本文寫於 2020 年 1 月 6 日react

示例代碼:https://github.com/AerospaceXu/hooks-soagit

React 社區最火的全局狀態管理庫一定是 Redux,可是 Redux 自己就是爲了大型管理數據而妥協設計的——這就會讓一些小一點的應用一旦用上 Redux 就變得複雜無比。github

後來又有了 Mobx,它對於小型應用的狀態管理確實比 Redux 簡單很多。但是不得不說 Mobx+React 簡直就是一個繁瑣版本的 Vue。redux

另外無論是 react-redux 仍是 mobx,他們使用的時候都很是複雜。須要你去組件函數或是組件類上修修改改,我我的從審美上來講就不是很喜歡。ide

後來用了 Angular 以後,我就開始對 SOA 產生好感,ng 的 Service 與依賴注入我都以爲很是漂亮。函數

Service 是 Angular 的邏輯複用形式,而且解決了共享狀態的問題,那 React 的自定義 Hook 能夠達到相似的效果嘛?spa

能夠,而且會比 Angular 更簡潔。設計

自定義 Service

材料:useXxxx(自定義 hook), createContext, useContextcode

咱們作一個最簡單的計數器吧:一個 button,一個 panel,button 用來增長,panel 用來展現。get

const App: React.FC = () => {
  return (
    <div>
      <Button />
      <Panel />
    </div>
  );
};

而後咱們來定義咱們的 Service:

// services/global.service.ts
interface State {
  count: number;
  handleAdd: () => void;
}

export const GlobalService = createContext<State>(null);

咱們選擇讓一個 Context 成爲一個 Service,這是由於咱們能夠利用 Context 的特性來進行狀態共享。

而後咱們建立一個自定義 Hook,而且在 Context.provider 中傳入該 Root Service:

// services/global.service.ts
export const useRootGlobalService = () => {
  const [count, setCount] = useState<number>(0);
  const handleAdd = useCallback(() => {
    setCount((n) => n + 1);
  }, []);

  return {
    count,
    handleAdd,
  };
};

接着咱們再建立一個自定義 Hook,讓咱們能夠隨時拿到該 Service:

// services/global.service.ts
export const useGlobalService = () => useContext(GlobalService);

接着咱們就能夠運用了

// App.tsx
import { GlobalService, useRooGlobalService } from './services/global.service';

const App: React.FC = () => {
  return (
    <GlobalService.Provider value={useRooGlobalService()}>
      <div>
        <Button />
        <Panel />
      </div>
    </GlobalService.Provider>
  );
};

// Button.tsx
import { useGlobalService } from '../services/global.service';

const Button: React.FC = () => {
  const { handleAdd } = useGlobalService();
  return <button onClick={() => handleAdd()}>+</button>;
};

// Panel.tsx
import { useGlobalService } from '../services/global.service';

const Panel: React.FC = () => {
  const { count } = useGlobalService();
  return <h2>{count}</h2>;
};

(完)

相關文章
相關標籤/搜索