如何利用 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>;
};

(完)

相关文章
相关标签/搜索