xaviergonz / mobx-keystone

A MobX powered state management solution based on data trees with first class support for Typescript, support for snapshots, patches and much more
https://mobx-keystone.js.org
MIT License
554 stars 25 forks source link

How to inherit ModelOptions when using ExtendedModel? #492

Closed wangzhewudiya closed 1 year ago

wangzhewudiya commented 1 year ago
import { model, Model, prop, ExtendedModel } from "mobx-keystone"

@model("MyApp/Point")
class Point extends Model({
  _version: prop(2),
  x: prop<number>(),
  y: prop<number>(),
}, {
  toSnapshotProcessor(sn, modelInstance) {
    console.log("toSnapshotProcessor")
    return {
      ...sn,
    }
  },
}) {
  get sum() {
    return this.x + this.y
  }
}

@model("MyApp/Point3d")
class Point3d extends ExtendedModel(Point, {
  z: prop<number>(1),
}) {
  get sum() {
    return super.sum + this.z
  }
}

// will output toSnapshotProcessor
export const point = new Point({
  x: 1,
  y: 2,
})

// will not output toSnapshotProcessor
export const point3d = new Point3d({
  x: 1,
  y: 2,
})

ModelOptions is configured on Point, but instantiating Point3d will not execute ModelOptions. How can I make ModelOptions on Point take effect?

xaviergonz commented 1 year ago

That's working as expected, from/to snapshot processors are not shared across model extensions.

If you want to share them you can extract them to a shared function and call it on each model's toSnapshotOptions.

For example:

import { model, Model, prop, ExtendedModel } from "mobx-keystone"

function sharedToSnapshotProcessor(sn: WhateverSnType, modelInstance: WhateverModelInstance) {
    console.log("toSnapshotProcessor")
    return {
      ...sn,
    }
}

@model("MyApp/Point")
class Point extends Model({
  _version: prop(2),
  x: prop<number>(),
  y: prop<number>(),
}, {
  toSnapshotProcessor(sn, modelInstance) {
    return sharedToSnapshotProcessor(sn, modelInstance);
  }, // or toSnapshotProcessor: sharedToSnapshotProcessor
}) {
  get sum() {
    return this.x + this.y
  }
}

@model("MyApp/Point3d")
class Point3d extends ExtendedModel(Point, {
  z: prop<number>(1),
}, {
  toSnapshotProcessor(sn, modelInstance) {
    return sharedToSnapshotProcessor(sn, modelInstance);
  }, // or toSnapshotProcessor: sharedToSnapshotProcessor
}) {
  get sum() {
    return super.sum + this.z
  }
}