useCreateViewModel hook
A hook that connects a ViewModel (or ViewModelSimple) to the React render tree, providing seamless MobX integration.
It is used inside the withViewModel() HOC.
API Signature
function useCreateViewModel<VM extends AnyViewModel>(
ViewModelClass: Class<VM>,
payload?: ViewModelPayload<VM>,
config?: UseCreateViewModelConfig<VM>
): VM;Configuration
| Option | Description |
|---|---|
id | Stable instance id. Defaults to React useId(). |
factory | Custom factory (same idea as viewModelsConfig.factory). |
vmConfig | Per-instance ViewModelsConfig overrides. |
ctx | Extra context object passed into create config. |
anchors | Extra lookup anchors for useViewModel. |
props | Original component props forwarded into create config. |
When a ViewModelStore is present (via ViewModelsProvider), the hook creates the VM in React's render-phase registry on the client and registers it with the store's connect() method only when the component's commit effect runs. React hooks and VM instances created by the hook can read this registry during render; direct reads from the core store see only committed VM instances. A render pass discarded by React (for example, a duplicate fiber under Suspense in React 19) therefore never mutates the store or leaves an orphaned VM behind. Otherwise the hook creates the instance via factory / global config and calls init / mount locally. Cleanup uses unmount (with store) or unmount() (without).
Keep ViewModelsProvider.value stable while the component is mounted. To switch stores, remount the provider subtree.
SSR
With viewModelsConfig.mode = 'ssr' on React 19+, if mount() / willMount() returns a Promise, the hook waits for it with React use() during SSR and the first client hydration. Wrap the tree in Suspense for a loading UI — the hook suspends before a parent HOC fallback can render.
On React 18, use() is unavailable, so the hook does not wait: the component can render while isMounted is still false. Use withViewModel's fallback, or gate on model.isMounted when calling this hook directly.
Usage
1. Basic Usage (Default Configuration)
import { useCreateViewModel } from "mobx-view-model-react";
import { observer } from "mobx-react-lite";
export const YourComponent = observer(() => {
const model = useCreateViewModel(YourVM);
return null;
});2. Usage with payload
import { useCreateViewModel } from "mobx-view-model-react";
import { observer } from "mobx-react-lite";
export const YourComponent = observer(() => {
const model = useCreateViewModel(YourVM, { userId: '1' });
return null;
});3. Custom Configuration
import { useCreateViewModel } from "mobx-view-model-react";
import { observer } from "mobx-react-lite";
export const YourComponent = observer(() => {
const model = useCreateViewModel(YourVM, {}, {
ctx: {}, // extra create-config context
id: 'your-component', // explicit id for one shared VM instance
anchors: [], // additional components for useViewModel lookup
});
return null;
});Example:
import { ViewModelBase } from "mobx-view-model";
import { useCreateViewModel } from "mobx-view-model-react";
import { observer } from "mobx-react-lite";
import { observable, action } from "mobx";
class VM extends ViewModelBase {
@observable
accessor value = '';
@action
setValue = (value: string) => {
this.value = value;
}
}
export const YourComponent = observer(() => {
const model = useCreateViewModel(VM)
return (
<div>
<input value={model.value} onChange={e => model.setValue(e.target.value)} />
</div>
)
})