MobX Vue helper
    Preparing search index...

    MobX Vue helper

    MobX-Vue-helper

    MobX Class & JSX helpers for Vue 3 components, providing seamless integration with MobX state management for both class and function components.

    NPM publishing NPM License: LGPL v2.1

    • 🎯 Universal Support: Works with both class and function 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 to mobx-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:

    1. 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);
    2. 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.

    1. https://github.com/idea2app/MobX-React-helper
    2. https://github.com/idea2app/Vue-MobX-Prime-ts