【问题标题】:Best pattern for saving and loading MobX store to React Native AsyncStorage?将 MobX 存储保存和加载到 React Native AsyncStorage 的最佳模式?
【发布时间】:2018-09-13 05:50:21
【问题描述】:

我有一个使用 MobX 的 React Native 应用程序。我的商店有一个默认对象,当用户使用操作(在 Options.js 文件中)更新值时,我想将其保存在本地(React Native 的 AsyncStorage),以便下次打开应用程序时对象未重置为默认值。在首次运行、检查和加载新值时处理这个问题的好模式是什么?

我的 RootStore.js 看起来像这样:

import { observable, action } from 'mobx';

export default class RootStore {
  constructor() {
    this.sources = new Sources(this);
  }
}

class Sources {
  constructor(rootStore) {
    this.rootStore = rootStore;
  }
  @observable
  left = [
    {
      active: 'yes',
      side: 'value One',
      name: 'value Two',
    },
  ];
//passing in new object from Options.js
  @action
  updateActiveLeft(data) {
    let object = data;
    this.left = object;
    console.log('New active name set in store - ' + this.left[0].name);
  }

【问题讨论】:

    标签: javascript react-native mobx


    【解决方案1】:

    我已更新您的文件以包含我在所有 React Native 应用程序中一直使用的基本模式。我使用 async/await 语法来处理异步调用,但你可以使用 Promise 或任何你喜欢的模式。你可能还想让它成为一个 DRY 类来处理你所有的本地 API。请注意,如果您将非 mobx 方法存储在您的商店中,这将不起作用,因为mobx.toJS 不会删除它们并且JSON.stringify 不能序列化函数。

    编辑:修复编译错误并添加 updateStore() 方法。

    import { observable, action, toJS } from 'mobx';
    import { AsyncStorage } from 'react-native';
    import _ from 'lodash';
    
    export default class RootStore {
      constructor() {
        this.sources = new Sources(this);
        // You can move this to your App.js class when your app
        // for more control but this will start loading your data
        // as soon as RootStore is created.
        this.sources.refreshStores();
      }
    }
    
    class Sources {
    
      @observable
      left = [
        {
          active: 'yes',
          side: 'value One',
          name: 'value Two',
        },
      ];
    
      //passing in new object from Options.js
      @action
      updateActiveLeft(data) { // May want to make this a promise or async
        let object = data;
        // this.left = object; // Now using updateStore to set MobX obs
        this.updateStore(toJS(object)).then(() => {
          console.log('Data is now saved in AsyncStorage.')
        });
      }
    
      /**
       * Set async data to local memory
       * @param newdata {object} An updated store abject
       */
      @action
      updateStore = async (newdata) => {
        try {
          const AppData = newdata;
          // Set MobX observables with new data
          _.forEach(AppData, (value, key) => {
            this[key] = value;
          });
          // Set AsyncStorage
          await AsyncStorage.setItem('app', JSON.stringify(AppData));
        } catch(e) {
          console.log('Could not update app store. [store/App]')
        }
      }
    
      /**
       * Set MobX data from AsyncStorage
       */
      @action
      refreshStores = async () => {
        try {
          const RootStore = await this.getStore();
          // I store my data in AsyncStorage exactly the same way I store my observables
          // so that when I recall them I can just iterate through my object or array
          // and set them easily to MobX observables.
          _.forEach(RootStore, (value, key) => {
            this[key] = value;
          });
        } catch(e) {
          console.log('Could not refresh app store.');
        }
      }
    
      /**
       * Retrieve data from AsyncStorage
       */
      @action
      getStore = async () => {
        try {
          // I'm just using RootStore as a storage key name but you can use whatever you want.
          // I'm also shortcircuiting the call to async to be replaced with the default values
          // in case the store doesn't exist.
          let RootStore = await AsyncStorage.getItem('RootStore') || JSON.stringify(toJS(this));
          RootStore = JSON.parse(RootStore);
          return RootStore;
        } catch(e) {
          console.log('Could not get data from store.')
        }
      }
    
    }
    

    【讨论】:

    • 酷。我已经添加了这个(需要来自 react-native 和 lodash 的 toJS,对吗?)。但是我在 console.log 中收到“无法从存储中获取数据”...?
    • 对不起。是的,它是 lodash。您能否在 getStore() 方法的 catch 语句中记录实际错误。 console.log(e); 应该足够了。
    • 当然! TypeError: (0 , _reactNative.toJS) 不是函数
    • 又一个依赖忘记了!将 MobX 导入更新为如下所示。 `import { observable, action, toJS } from 'mobx'. toJS() 所做的只是将 MobX 可观察对象转换为您可以存储的真实对象/数组。否则,您将存储 MobX 为您创建的对象。让我知道这是否有效。
    • @AdamGerthel 是的。我只是从本地存储加载键/值,但这些可以是嵌套对象或多维数组。您可能需要修改 refreshStores() 以适应您的反应性子句
    【解决方案2】:

    您可以尝试使用来自mobx-decorators@save 装饰器。但请记住@save 是惰性装饰器,值将在第一次访问属性后加载。

    【讨论】:

      猜你喜欢
      • 2018-01-22
      • 1970-01-01
      • 1970-01-01
      • 2018-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-16
      相关资源
      最近更新 更多