最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • mobx-react@7.x 的使用

    正文概述 掘金(Darcrandex)   2021-01-07   455

    原文链接

    mobx-react@7.x hooks

    前言

    mobx-react@7.x相较于mobx-react@6.x有很大改变, api 也有所不同. 因此写法有改变. 另外本例子是基于react@17.0.1+react hooks+mobx@6.x + mobx-react@7.x+ typescript创建的.

    如何定义子模块

    mobx-react@7.x提供了makeAutoObservable方法, 用来将普通对象转化为可观察对象. 官方文档的例子中是在constructor中进行转化的.

    // /src/store/timer.ts
    
    class Timer {
      secondsPassed = 0;
      constructor() {
        makeAutoObservable(this);
      }
      increaseTimer() {
        this.secondsPassed += 1;
      }
    }
    

    但是经过测试, 只需要最终引用的实例对象被转化即可

    class Timer {
      secondsPassed = 0;
      increaseTimer() {
        this.secondsPassed += 1;
      }
    }
    
    const timer = makeAutoObservable(new Timer());
    

    另外, 例子中的子模块类的属性方法并没有使用装饰器, 也可以正常运行. 但是会存在引用方法时, this指向错误的问题.

    <button onClick={timer.increaseTimer}>increaseTimer</button>
    
    // 报错: 'this.secondsPassed' is not defind
    

    所以延续旧的装饰器写法

    class Timer {
      @observable
      secondsPassed = 0;
    
      @action
      increaseTimer = () => {
        this.secondsPassed += 1;
      };
    }
    
    const timer = makeAutoObservable(new Timer());
    

    定义 stroe 总模块

    mobx-react@7.x中, 推荐使用React Context来存储状态. Using external state in observer components

    先来看总览的代码

    // /src/store/index.tsx
    
    import { FC, createContext, useContext } from "react";
    
    import timer from "./timer";
    
    const createStore = () => ({ timer });
    
    const storeValue = createStore();
    
    type TStore = ReturnType<typeof createStore>;
    
    const StoreContext = createContext<TStore | null>(null);
    
    export const StoreProvider: FC = ({ children }) => (
      <StoreContext.Provider value={storeValue}>{children}</StoreContext.Provider>
    );
    
    export const useStores = () => {
      const store = useContext(StoreContext);
      if (!store) {
        throw new Error("no store");
      }
      return store!;
    };
    

    先讲讲createContextuseContext. use context中提到, 创建出来的context类似一个容器, 用来缓存数据,Provider为提供数据的容器组件,其中的value属性则用来配置数据. 而useContext则会往上找到指定的context中保存的数据.

    创建context

    Version 1

    const store = { timer }; // 其中'timer'是上文定义的子模块
    const StoreContext = createContext(null);
    
    <StoreContext.Provider value={store} />;
    

    这样写是没有问题的. 但是会出现一点小问题. 当逻辑组件引用store的时候, 1.会提示store可能是null(即初始值), 2.不能明确store中包含的内容.

    function App() {
      const store = useContext(StoreContext);
    
      // 'store' 可能为空, 由于没有定义类型接口, 'timer' 是不明确的
      const secondsPassed = store?.timer?.secondsPassed;
    
      return "";
    }
    

    Version 2 先给 stroe 定义子模块的类型

    const createStore = () => ({ timer });
    const storeValue = createStore();
    type TStore = ReturnType<typeof createStore>;
    const StoreContext = createContext<TStore | null>(null);
    

    其中ReturnType<typeof createStore>是根据这篇文章 来使用的, 具体的原理还不是很明白, 先这样写. createContext接收泛型参数TStore后就能在引用时获得提示. 然后在导出useStores时, 使用!明确store一定存在.

    export const useStores = () => {
      const store = useContext(StoreContext);
      if (!store) {
        throw new Error("no store");
      }
      return store!;
    };
    

    创建关联 contextProvider

    export const StoreProvider: FC = ({ children }) => (
      <StoreContext.Provider value={storeValue}>{children}</StoreContext.Provider>
    );
    

    该组件注入storeValue, 然后组件内的所有子组件children都可以获取到context的数据.

    提供获取 store 的自定义 hooks

    export const useStores = () => {
      const store = useContext(StoreContext);
      if (!store) {
        throw new Error("no store");
      }
      return store!;
    };
    

    其中store就是上文创建的storeValue

    在根组件中使用 Provider

    一般在/src/index.tsx

    import { StoreProvider } from "@/store";
    
    ReactDOM.render(
      <StoreProvider>
        <App />
      </StoreProvider>,
      document.getElementById("root")
    );
    

    在子孙组件中引用

    // /src/pages/MyComponent.tsx
    
    import { observer } from "mobx-react";
    import { useStores } from "@/store";
    
    function MyComponent() {
      const { timer } = useStores();
    
      return (
        <>
          <p>Seconds passed: {timer.secondsPassed}</p>
          <button onClick={timer.increaseTimer}>increaseTimer</button>
        </>
      );
    }
    
    export default observer(MyComponent);
    

    最后不要忘了用observer来将组件转为观察者.


    起源地下载网 » mobx-react@7.x 的使用

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元