Skip to content

ViewModel interface ​

Interface that defines the core functionality for implementing the MVVM pattern in your application.
All code examples will include the base implementation of this interface.

Reference to source code

API Signature ​

ts
interface ViewModel<Payload, ParentViewModel>

Generics ​

1. Payload ​

Declares the payload data type for your ViewModel. Used for transferring data between view models or views.
Must be an object type or EmptyObject for no payload.

2. ParentViewModel ​

Declares the parent ViewModel / ViewModelSimple type where current ViewModel is rendered in the component hierarchy.
Enables access to parent view model through the parentViewModel property.
Optional, defaults to null if not specified.

Core Properties ​

id: string ​

Unique identifier for the view model instance.
Used for tracking and managing view model lifecycle.

payload: Payload ​

Data object passed from the parent component to the view model.

vm: ViewModelInfo ​

Metadata exposed by the view model. Its state describes the current lifecycle state, and data contains data returned by the configured ViewModelResource for this view model's id (or undefined when no resource is configured).

ts
import { ViewModelBase } from 'mobx-view-model';

type Product = { id: string; title: string };

class ProductVM extends ViewModelBase {
  get product(): Product {
    return this.vm.data as Product;
  }
}

isMounted: boolean ​

Indicates whether the ViewModel is currently mounted with its associated component.
Controls the rendering of the connected view component:

  • true: Component is rendered
  • false: Component is not rendered

isHydrated: boolean ​

Indicates whether the ViewModel was hydrated from SSR data.

vm.state: ViewModelLifecycleState ​

The current lifecycle state of the ViewModel, exposed through vm. Possible values:

StateDescription
'init'Instance created, mount() not yet called
'mounting'mount() is in progress (async willMount() running)
'mounted'Fully mounted, isMounted is true
'hydrated'Hydrated from SSR data; isMounted is true
'unmounting'unmount() started
'unmounted'Fully unmounted

vm.state is a MobX observable.ref — you can observe it in reactions or use it to distinguish between init (not yet mounted) and mounting (mount in progress), which isMounted alone cannot do. The vm metadata object also exposes resource data as vm.data.

parentViewModel: ParentViewModel ​

Reference to the parent ViewModel in the component hierarchy.

WARNING

This property is only available when using:

Example: Parent-Child ViewModel Communication ​

ts
import { ViewModelBase } from "mobx-view-model";

class ParentVM extends ViewModelBase {
  foo = 'bar'
}

class ChildVM extends ViewModelBase<{}, ParentVM> {
  get baz() {
    return this.parentViewModel?.foo; // 'bar'
  }
}

Lifecycle Methods ​

init?(config: ViewModelInitConfig<this>): void ​

Optional hook called when the instance is connected to a ViewModelStore (for example via define / connect). Also called by the React / Solid integrations when creating a VM without a store.

mount(): void | Promise<void> ​

Called when the component is mounted in the React / Solid tree.

TIP

In ViewModelBase, prefer putting async work in willMount() — it may return a Promise, and mount() waits for it before setting isMounted to true.

Example: Async Mounting ​

ts
import { ViewModelBase } from "mobx-view-model";

class JediProfileVM extends ViewModelBase<{ jediId: string }> {
  protected async willMount() {
    await this.loadJediData();
  }

  private async loadJediData() {
    const response = await fetch(`/api/jedi/${this.payload.jediId}`);
    this.jediData = await response.json();
  }
}

unmount(): void ​

Called when the component is unmounted from the React / Solid tree.

TIP

ViewModelBase sets isMounted to false during this method and aborts unmountSignal.

Payload Management ​

setPayload(payload: Payload): boolean ​

Updates the view model's payload data.

Returns true when the new payload is considered equal to the current one (no update applied), and false when the payload was updated.

React / Solid integration

React applies payload updates to an existing view model after the render commits. Initial ViewModelSimple binding and Solid setup may still call setPayload before mount() finishes, when isMounted is false. Guard any work in setPayload that requires a mounted view model.

TIP

When extending ViewModelBase, do not assign to this.payload directly (it is a getter): call super.setPayload(payload) or customize comparison with comparePayload.

Example: Payload Update with Validation ​

ts
import { ViewModelBase } from "mobx-view-model";
import { runInAction } from "mobx";

class LightsaberVM extends ViewModelBase<{ jediId: string }> {
  @observable
  accessor currentJediId: string | null = null;

  setPayload(payload: { jediId: string }) {
    if (this.currentJediId !== payload.jediId) {
      runInAction(() => {
        this.currentJediId = payload.jediId;
      });
    }
    return super.setPayload(payload);
  }
}