Skip to content

The action "createObservableInstanceIfNeeded" is run every time object is accessed #1421

@Venryx

Description

@Venryx

Bug report

  • I've checked documentation and searched for existing issues
  • I've made sure my project is based on the latest MST version
  • Fork this code sandbox or another minimal reproduction.

Sandbox link or minimal reproduction code
https://codesandbox.io/s/mobx-state-tree-todolist-uo625

Describe the expected behavior
I expect that merely accessing data within a MST tree will not cause actions to be dispatched, which show up in the MobX devtools and make it hard to see the "real" actions.

Describe the observed behavior
Every time ComplexType.prototype.getValue is called, it runs the below:

getValue(node: this["N"]): T {
node.createObservableInstanceIfNeeded()
return node.storedValue
}

As can be seen, it calls node.createObservableInstanceIfNeeded(). The problem is, node.createObservableInstanceIfNeeded is a method with the @action decorator applied. Thus, every time a ComplexType's value is retrieved, it causes an action to be dispatched, which has the negatives described earlier (pollutes the MobX dev-tools Changes panel).

I know the MobX dev-tools Changes panel lets you set a "filter" that hides certain changes (eg: /^(?!createObs)).

However:

  1. The filter does not persist between page refreshes.
  2. It's an unpleasant workaround that new developers should not have to figure out on their own.
  3. It may block out legitimate instances of that call that the developer might want to still see.

My suggestion: Split the method into two parts.

createObservableInstanceIfNeeded(): void {
	if (this._observableInstanceState !== ObservableInstanceLifecycle.UNINITIALIZED) {
		return
	}
	this.createObservableInstance()
}

@action
createObservableInstance(): void {
	[...]
}

Basically: Split off the portion that needs to be in an action into a separate createObservableInstance method. This way, for the 90%+ of times where you're just reading the value (and you don't need to create a new observable instance), the "if needed" check in the non-action part will see that an observable doesn't need to be created, thus avoiding the need to call the method with the @action decorator, thus greatly cutting down on extraneous actions that show up in the Changes panel.

I can create a pull-request for this change (as it's very simple -- just the code above), however want to bring it up in an issue first to make sure it's the desired solution to the problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions