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.
API Signature
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).
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 renderedfalse: 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:
| State | Description |
|---|---|
'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:
ViewModelStore(integrated with ViewModelsProvider)withViewModelHOC
Example: Parent-Child ViewModel Communication
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
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
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);
}
}