MobX Class & JSX helpers for Vue 3 components, providing seamless integration with MobX state management for both class and function components.
- π― Universal Support: Works with both
class
andfunction
components - π Auto Reactivity: Automatically tracks and reacts to MobX observable state changes
- β‘ Reaction Decorator:
@reaction()
decorator for declarative side effects on observable changes - π¨ TypeScript First: Full TypeScript support with type definitions
- π Easy to Use: Simple
@observer
decorator API, similar tomobx-react
- πͺ Vue 3 Compatible: Built for Vue 3 with composition API support
npm install mobx mobx-vue-helper vue-facing-decorator
import { Vue, Component, toNative } from 'vue-facing-decorator';
import { observer } from 'mobx-vue-helper';
import counterStore from './models/Counter';
@Component
@observer
class MyMobX extends Vue {
render() {
return <button onClick={() => counterStore.increment()}>Count: {counterStore.count}</button>;
}
}
export default toNative(MyMobX);
import { observer } from 'mobx-vue-helper';
import counterStore from './models/Counter';
export const MyMobX = observer(() => (
<button onClick={() => counterStore.increment()}>Count: {counterStore.count}</button>
));
import { observable } from 'mobx';
export class CounterStore {
@observable
accessor count = 0;
increment() {
this.count++;
}
decrement() {
this.count--;
}
}
export default new CounterStore();
The @reaction()
decorator allows you to define side effects that run when specific observable values change. It's based on MobX's reaction()
.
import { Vue, Component, toNative } from 'vue-facing-decorator';
import { observer, reaction } from 'mobx-vue-helper';
import counterStore from './models/Counter';
@Component
@observer
class MyComponent extends Vue {
// This method will be called whenever count changes
@reaction(() => counterStore.count)
handleCountChange(newValue: number, oldValue: number) {
console.log(`Count changed from ${oldValue} to ${newValue}`);
}
render() {
return <button onClick={() => counterStore.increment()}>Count: {counterStore.count}</button>;
}
}
export default toNative(MyComponent);
Note: The @reaction()
decorator should be used with the @observer
decorator on the class. Reactions are automatically disposed when the component is unmounted.
The @observer
decorator wraps your component's render function with MobX's <Observer />
component from mobx-vue-lite
. This enables automatic tracking of observable access during render and triggers re-renders when tracked observables change.
- For class components: The decorator uses class inheritance to extend your original component, wrapping the
render()
method and managing MobX reactions lifecycle - For function components: The wrapper creates a Vue component with a setup function that wraps your functional component
The @reaction()
decorator allows you to define MobX reactions directly on class methods. These reactions are automatically initialized when the component mounts and disposed when it unmounts.
As the implementation of Vue 3 & Vue-facing-decorator are dependent on Proxy
API, and MobX 6+ & ES Decorator stage-3 are dependent on accessor
properties (which is used the Private Field inside), it'll throw errors when they are working together, so we can't put @observable
on fields of class components directly as React & WebCell do.
There're 2 alternatives to work around this:
-
create a separate store class with
@observable
properties and use it inside your Vue class component.import { Vue, Component, toNative } from 'vue-facing-decorator'; import { observable } from 'mobx'; import { observer } from 'mobx-vue-helper'; class State { @observable accessor count = 0; increment() { this.count++; } decrement() { this.count--; } } @Component @observer class MyMobX extends Vue { state = new State(); render() { const { state } = this; return <button onClick={() => state.increment()}>Count: {state.count}</button>; } } export default toNative(MyMobX);
-
use
makeAutoObservable(this)
in the constructor of your Vue class component to make all properties observable.import { Vue, Component, toNative } from 'vue-facing-decorator'; import { observer } from 'mobx-vue-helper'; import { makeAutoObservable } from 'mobx'; @Component @observer class MyMobX extends Vue { count = 0; constructor() { super(); makeAutoObservable(this); } increment() { this.count++; } decrement() { this.count--; } render() { return <button onClick={() => this.increment()}>Count: {this.count}</button>; } } export default toNative(MyMobX);
- TypeScript 5.x
- Vue 3.x
- MobX 6.x
- Vue-facing-decorator 4.x
This package is part of the idea2app ecosystem and is inspired by the observer pattern from mobx-react
.