MobX Class & JSX helpers for Vue 3 components, providing seamless integration with MobX state management for both class and function components.
class and function components@reaction() decorator for declarative side effects on observable changes@observer decorator API, similar to mobx-reactnpm 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();
@reaction() DecoratorThe @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.
render() method and managing MobX reactions lifecycleThe @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);
This package is part of the idea2app ecosystem and is inspired by the observer pattern from mobx-react.