---
url: /mobx-view-model/api/view-models/base-implementation.md
---

# `ViewModelBase` class

This is the base implementation of the [`ViewModel`](/api/view-models/interface) interface.

[Reference to source code](/src/view-model/view-model.base.ts)

## Methods and properties

Here is documentation about **base implementation** methods and properties.

::: info
If you want to read about [`ViewModel`](/api/view-models/interface) interface methods and properties [go to interface documentation](/api/view-models/interface)\
:::

### `viewModels`

Reference to an instance of [`ViewModelStore`](/api/view-model-store/overview).\
Allows access to other [`ViewModels`](/api/view-models/interface).

#### Example

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

export class SithCardVM extends ViewModelBase {
  get power() {
    return this.viewModels.get(JediCardVM)?.power ?? 0;
  }
}

export class StarWarsBattlefieldVM extends ViewModelBase {
  get jedisCount() {
    return this.viewModels.getAll(JediCardVM).length;
  }

  get sithsCount() {
    return this.viewModels.getAll(SithCardVM).length;
  }
}
```

### `unmountSignal`

This is an [`AbortSignal`](https://developer.mozilla.org/ru/docs/Web/API/AbortSignal) that is signaled when your [`ViewModel`](/api/view-models/interface) is unmounted. It happens after `unmount()` completes in the base implementation. If the same view model instance is mounted again, the base implementation creates a fresh signal; the signal from the previous mount remains aborted.

#### Example

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

export class TestVM extends ViewModelBase {
  protected willMount() {
    autorun(
      () => {
        console.log("log", this.id, this.isMounted);
      },
      {
        signal: this.unmountSignal
      }
    );
  }
}
```

### `vm: ViewModelInfo`

Metadata for this view model. `vm.state` contains its lifecycle state and
`vm.data` contains data loaded from the configured resource. See the
[`ViewModel` interface](/api/view-models/interface#vm-viewmodelinfo) for the
state values and a resource-data example.

### `isMounted: boolean`&#x20;

Indicates whether the `ViewModel` is currently mounted with its associated component.

### `willMount(): void | Promise<void>`  {#willmount-void}

Called when the component begins mounting.\
Executes before `isMounted` becomes `true`.

May return a `Promise` — `mount()` waits for it, then finalizes mounting. Prefer this over overriding `mount()` for async setup.

### `mount(): void | Promise<void>`&#x20;

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

This method sets [`isMounted`](/api/view-models/interface#ismounted-boolean) to `true` after [`willMount()`](#willmount-void) completes.\
If you override this method, be sure to call [`super.mount()`](/api/view-models/interface#mount-void-promise-void);
otherwise your view component connected to this `ViewModel` will never be rendered
because the [`withViewModel`](/react/api/with-view-model) HOC checks the [`isMounted`](/api/view-models/interface#ismounted-boolean) flag before rendering the view component.

#### Example: Async work in `willMount`

```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();
  }
}
```

### `didMount(): void`&#x20;

Called after the view model is fully mounted and ready for use.\
Ideal for post-mount initialization and side effects.

#### Example: Post-Mount Actions

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

class ForceAlertVM extends ViewModelBase<{ message: string }> {
  protected didMount() {
    this.rootStore.notifications.push({
      type: 'success',
      title: "May the Force be with you!",
      message: this.payload.message
    });
  }
}
```

### `willUnmount(): void`&#x20;

Called when the component begins unmounting from the React / Solid tree.\
Executes before the `unmount()` method finishes.

### `unmount(): void`&#x20;

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

This method sets [`isMounted`](/api/view-models/interface#ismounted-boolean) to `false` and aborts [`unmountSignal`](#unmountsignal).\
If you override this method, be sure to call [`super.unmount()`](/api/view-models/interface#unmount-void);
otherwise your view component connected to this `ViewModel` will never be unmounted correctly.

### `didUnmount(): void`&#x20;

Called after the view model is fully unmounted.\
Ideal for final cleanup operations.

### [`setPayload(payload: Payload): boolean`](/api/view-models/interface#setpayload-payload-payload-boolean)

Updates the view model's payload data.

Returns `true` when the payload is considered equal (no change applied), and `false` when it was updated.

The base implementation of this method compares the current payload and the new payload before setting it.\
Configure the comparison with [`comparePayload`](/api/view-models/view-models-config#comparepayload):

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

class PostcardBox extends ViewModelBase<{ postcardId: string }> {}

new PostcardBox({
  id: "postcard-box",
  payload: { postcardId: "one" },
  vmConfig: {
    comparePayload: (current, next) => current?.postcardId === next.postcardId,
  },
});
```

To customize payload handling further, override `setPayload()` and call `super.setPayload(payload)` when appropriate.

### `hasChild(vm, deep?): boolean`  {#haschild-vm-anyviewmodel--anyviewmodelsimple-deep-boolean-boolean}

Checks whether the given view model is a child of the current view model.

* **Shallow** (`deep` is `false`/`undefined`): `vm.parentViewModel === this`
* **Deep** (`deep` is `true`): checks the whole parent chain of `vm` and returns `true` if it contains `this`

#### Example

```ts
class RootVM extends ViewModelBase {}
class ChildVM extends ViewModelBase {}

const root = new RootVM({ id: "root", payload: {} });
const child = new ChildVM({ id: "child", payload: {}, parentViewModel: root });

// inside RootVM
this.hasChild(child) // true
this.hasChild(child, true) // true
```

### `hasParent(vm, deep?): boolean`  {#hasparent-vm-anyviewmodel--anyviewmodelsimple-deep-boolean-boolean}

Checks whether the given view model is a parent of the current view model.

* **Shallow** (`deep` is `false`/`undefined`): `this.parentViewModel === vm`
* **Deep** (`deep` is `true`): checks the whole parent chain of `this` and returns `true` if it contains `vm`

#### Example

```ts
class RootVM extends ViewModelBase {}
class ChildVM extends ViewModelBase {}

const root = new RootVM({ id: "root", payload: {} });
const child = new ChildVM({ id: "child", payload: {}, parentViewModel: root });

// inside ChildVM
this.hasParent(root) // true
this.hasParent(root, true) // true
```

## Additional utility types

[Reference to source code](/src/view-model/view-model.base.types.ts)

### `InferViewModelParams<T>`

Utility type that infers constructor params for a `ViewModelBase` subclass.\
It resolves to `ViewModelParams<Payload, ParentViewModel, ComponentProps>` based on the class generics.

#### Example

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

class UserVM extends ViewModelBase<
  { userId: string },
  null,
  { isAdmin?: boolean }
> {
  constructor(params: InferViewModelParams<UserVM>) {
    params.vmConfig = {
      ...params.vmConfig,
      comparePayload: 'strict',
    };

    super(params);
  }
}
```

### `InferViewModelPayload<T>` / `InferViewModelProps<T>`

Helpers that extract `payload` and `props` types from a `ViewModelBase` subclass.
