【问题标题】:Does mobx-state-tree support nested models?mobx-state-tree 是否支持嵌套模型?
【发布时间】:2020-02-26 10:29:55
【问题描述】:

我有一个父模型和一个状态子模型,我想引用子模型中的操作,例如 item.pdf.download()

我已经创建了这样的解决方法:

const pdf = types.model({ state: ... })
const Item = types.model({ ... }).volatile(self => ({ pdf: pdf.create({ ... }) }))

但它看起来不像预期的方式,

有没有办法在 mobx-state-tree 中做嵌套模块?

【问题讨论】:

    标签: mobx-state-tree


    【解决方案1】:

    是的,如果事实上所有不是原始模型的东西都需要成为某个 MST 模型才能成为更大模型的一部分

    // Parent
    const ItemModel = types.model({
      pdf: types.optional(PdfModel, {}),
      // or when the child needs an initial data not provided by the snapshot
      // pdf: types.optional(PdfModel, { state: 'initial' }),
    
      // It can ofcourse be a list (or map) of child types, default value is []
      relatedPdfs: types.array(PdfModel),
    })
      .views(self => ({
        get downloaded() {
          return self.relatedPdfs.filter(pdf => pdf.state == 'complete');
        }
      }))
      .actions(self => ({
        async downloadAll() {
          const tasks = self.relatedPdfs.map(pdf => pdf.download());
          const results = await Promise.all(tasks);
    
          return results;
        }),
      }));
    
    // Child
    const PdfModel = types.model({
      state:  types.optional(types.enumeration(['initial', 'downloading', 'complete', 'error']), 'initial'),
      url: types.maybeNull(types.string),
    })
      .volatile(self => ({
        data: null,
      })),
      .actions(self => ({
        download: flow(function * download(url = self.url) {
          self.state = 'downloading';
          
          try {
            const data = await downloadTheData(url);
            
            self.state = 'complete';
            self.data = data;
           
            return data;
          }
          catch(e) {
            self.state = 'error';
          }
        }),
      }));
    

    可能的问题是,当您创建 parent 类型的实例时,您可能必须通过 types.optional() 或允许 @987654324 为整个树提供快照,或为任何子类型定义默认值@值通过types.maybe

    例如如果我们没有 types.optionaltype.maybeNull 子值 我们必须提供涵盖此内容的快照

      const snap = {
        pdf: { state: 'initial', url: 'http://example.com' },
      };
    
      const item = ItemModel.create(snap);
    

    但是由于我们已经覆盖了默认值,所以我们不需要初始快照

     const item = ItemModel.create();
    

    你当然可以提供一个快照来覆盖默认值

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      • 2021-12-24
      • 2019-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多