最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Mobx vs Recoil application

    正文概述 掘金(xfz)   2021-01-25   992

    前言

    • vue: vuex
    • react:redux、mobx(v4/5、v6)、recoil

    在这里,暂不细致比较 redux,就个人而言,不选择 redux 有以下几点

    • 首先 Redux 这一套的机制,React Hooks 本身就已经实现,useReducer、useContext,没有必要
    • 重要的一点,redux 数据流机制是从上至下传递,与当前流行的 “即插即用”的设计原则不符,并且开发成本较 mobx 与 recoil 要高(umi、dva除外,umi学习和维护成本较高、dva不太灵活,它们有些限制)

    整体对比

    • mobxjs/mobx (v6):https://github.com/mobxjs/mobx
    • facebook/Recoil :https://github.com/facebookexperimental/Recoil
    对比项mobxrecoil
    Github Star 数23.1k11.4kReact hooks 支持mobx v6 + mobx-react
    - mobx 是可观察数据对象工具,可以在react、vue、js项目中使用
    - mobx-react 是将可观察对象与react关联起来的工具
    无需额外辅助工具,天然支持UI与逻辑 解耦支持
    - react 调用 store的action,逻辑在store中处理
    不支持
    - react调用 recoil的 useRecoilState API,在组件中实现业务逻辑,比如:
    const [amount, setAmount] = useRecoilState(amountState)
    单例与多例- export default new Store() 内部实例化,为单例
    - export default Store,引用处实例化,为多例
    通过程序控制,较为灵活,便于定制化
    每一个atom 和 selector 都是单例数据流向(单项目)- globalStore => Root => React.FC
    - pageStore => React.FC
    atom[ => selector] => React.FC状态感应when,reaction不支持store间交互支持不支持常用 API 数(个)5+6+学习成本较低较低理解成本开发体验友好一般,甚至有点麻烦,不适合大型项目

    基本使用对比

    mobx

    • 以 testStore 为例
    import { makeAutoObservable, runInAction } from 'mobx';
    
    class TestStore {
      amount = 1; // observable state
      data; // observable state
    
      constructor() {
        // 自动监听所有属性
        makeAutoObservable(this);
      }
      
      // computed
      get price(): string {
        return `$${this.amount * 100}`;
      }
      
      // action
      increment(): void {
        this.amount++;
      }
      
      // async action,
      async asyncAction(id: string): Promise<void> {
        try {
          const data = await geAsyncData(id);
          // 异步action中,改变状态时,外层要包裹 runInAction(() => {/** ...*/})
          runInAction(() => {
            this.data = data;
          });
        } catch (e) {
          throw new Error(e);
        }
      }
    }
    
    export default new TestStore();
    
    • Use In React:需结合 mobx-react
    import { FC } from 'react';
    import { observer } from 'mobx-react';
    import store from './testStore';
    
    const Test: FC = () => {
      return (
        <div>
          <div>count: {store.amount}</div>
          <div>price: {store.price}</div>
          <button type="button" onClick={() => store.increment()}>add +1</button>
          <button type="button" onClick={() => store.asyncAction(1)}>异步请求</button>
        </div>
      );
    };
    
    // 监听 Component
    export default observer(Test);
    

    recoil

    • recoil 的数据都是粒子,铺平的,
    import { atom, selector } from 'recoil';
    
    // state
    export const amountState = atom({
      key: 'amountState',
      default: 0,
    });
    
    // computed
    export const priceState = selector({
      key: 'priceState',
      get: ({ get }) => {
        return `$${get(amountState) * 100}`; ;
      }
    });
    
    // async state request
    export const asyncTestData = selector({
      key: 'asyncTestData',
      get: async ({ get }) => {
        return await geAsyncData();
      }
    });
    
    // what's the fuck,if you want request async data with params in recoil-store, you must use another API "selectorFamily"
    
    // async state request with params
    export const asyncTestDataWithParams = selectorFamily({
      key: 'asyncTestDataWithParams',
      get: id => async ({ get }) => {
        return await geAsyncData(id);
      }
    });
    
    • Use In React
    import { FC } from 'react';
    import { useRecoilState, useRecoilValue } from 'mobx-react';
    import { amountState, priceState, asyncTestDataWithParams } from './testStore';
    
    const Test: FC = () => {
      const [amount, setAmount] = useRecoilState(amountState);
      const price = useRecoilValue(priceState);
      
      const getData = () => {
      	return userRecoilValue(asyncTestDataWithParams(1));
      }
      
      return (
        <div>
          <div>count: {amount}</div>
          <div>price: {price}</div>
          <button type="button" onClick={() => setAmount(amount + 1)}>add +1</button>
          <button type="button" onClick={() => getData()}>异步请求</button>
        </div>
      );
    };
    
    // 监听 Component
    export default observer(Test);
    

    状态感应

    • 状态感应:当AStore的某个可观察数据达到条件时,会自动触发本store的其他动作 或 触发其他store的动作,程序描述就是 when(A.isReady === true) => B.action()
    • recoil 粒子说,不存在此场景
    • mobx 支持状态感应场景
    class TestStore {
      isReady = false;
      count = 0;
    
      constructor() {
        makeAutoObservable(this);
        // 监听isReady,当 isReady 变为 true 时,执行 doSomething(一次性行为)
        when(() = this.isReady, () => this.doSomething());
        // 监听amount,当 amount 每次变化后,都会输出 value, previousValue
        reaction(
          () => this.amount,
          (value, previousValue) => {
            console.log(value, previousValue);
          }
        );
      }
      
      doReady(): void {
        this.isReady = true;
      }
      
      doSomething(): void {
        ...
      }
      
      increment(): void {
        this.amount++;
      }  
    }
    

    Store间交互

    • recoil:不支持
    • mobx:基于 store实例的单例模式,且 store之间可以互相引用和调用,可以实现通过store来控制数据流的初始化控制
    import stores from './installStores';
    class ScheduleStore {
      isRunning = false;
      constructor() {
        makeAutoObservable(this);
      }
      async run(): Promise<void> {
        try {
          // 用户信息初始化
          await stores.userStore.init();
          await stores.testStore.init();
          runInAction(() => {
            this.isRunning = true;
          });
        } catch (e) {
          console.log(e);
        }
      }
    }
    

    Store形式

    • mobx: 一个 store 为一个class,便于功能扩展:继承 class、实现接口
    • Recoli:一个个粒子store,无法扩展,承接高级用法

    尾声

    mobx 与 recoil 基本对比分析已经OK、总之,各有各的特点,都是非常优秀数据管理工具,在技术选型时,还需参考项目实际应用场景和开发成本,希望本文能对你有所有帮助。

    如果想继续了解 mobx ,可以阅读 react hooks + mobx usage of summary

    参考文献

    ❤️ 加入我们

    字节跳动 · 幸福里团队

    Nice Leader:高级技术专家、掘金知名专栏作者、Flutter中文网社区创办者、Flutter中文社区开源项目发起人、Github社区知名开发者,是dio、fly、dsBridge等多个知名开源项目作者

    期待您的加入,一起用技术改变生活!!!

    招聘链接: job.toutiao.com/s/JHjRX8B


    起源地下载网 » Mobx vs Recoil application

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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