question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[RFC] mobx-vue v3

See original GitHub issue

Introduction

Since mobx v6 and vue v3 was released for a while, it’s time to support mobx v6 and vue v3.

Current Feature Request

Vue 3 Compatibility #50 Module Browser Build #49 Can I use mobx-vue without decorated class properties? #47 Add Documentation re Optimizing Rendering #36 Nuxt support #26 #32

Deprecate vue-class-component

Thoughts about mobx-vue https://github.com/mobxjs/mobx-vue/issues/3#issuecomment-573934357

I’m kinda wondering what direction this project might take with a “new vue” on the horizon. Since vue seems to move away from classes and therefore decorators is there a happy path to using mobx with vue in 2020?

vue-class-component has their own problem https://github.com/vuejs/vue-class-component/issues/406

Naive proto design (only for vue3)

No.1 idea

export a vue plugin for vue3

import { createApp } from 'vue';
import MobxVuePlugin from 'mobx-vue';
import App from './App.vue';

createApp(App)
    .use(MobxVuePlugin, { name: 'MyObserver' /** optional Observer component name */ })
    .mount('#app');

Using Observer Component in your app

<template>
  <Observer>
    <div>name: {{data.name}}</div>
    <button @click="changeName">change</button>
  </Observer>
</template>

<script setup>
  import { runInAction, observable } from mobx;
  const data = observable({ name: "iChenLei" });
  const changeName = () => {
   runInAction(() => { data.name = "Kuitos" });
 };
</script>

No.2 idea

export a observer function to hack vue export default, no need to install as plugin, you can use it directly.

<template>
  <UserComponent />
  <ProfileComponent />
</template>

<script>
  import { observer } from 'mobx-vue';
  export default observer({
      setup() {
        // balabala
      }
  });
</script>

<!-- use @ decorator -->
<script>
  import { observer } from 'mobx-vue';
  @observer
  export default {
      setup() {
        // balabala
      }
  };
</script>

But it not easy to do this , we need hack the vue @internel (e.g. $, $options, $forceUpdate)

// vue 3 internal component properties map
const publicPropertiesMap: PublicPropertiesMap = extend(Object.create(null), {
  $: i => i,
  $el: i => i.vnode.el,
  $data: i => i.data,
  $props: i => (__DEV__ ? shallowReadonly(i.props) : i.props),
  $attrs: i => (__DEV__ ? shallowReadonly(i.attrs) : i.attrs),
  $slots: i => (__DEV__ ? shallowReadonly(i.slots) : i.slots),
  $refs: i => (__DEV__ ? shallowReadonly(i.refs) : i.refs),
  $parent: i => getPublicInstance(i.parent),
  $root: i => getPublicInstance(i.root),
  $emit: i => i.emit,
  $options: i => (__FEATURE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type),
  $forceUpdate: i => () => queueJob(i.update),
  $nextTick: i => nextTick.bind(i.proxy!),
  $watch: i => (__FEATURE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP)
} as PublicPropertiesMap)

And when you use <script setup>, it’s also diffcult to implement a useful observer function.(any suggestion for this welcome)

No.3 idea

add the template sugar like <template pug>, <template functional>.

<tempalte observer>
  <UserProfile />
<template>

It looks like best solution for mobx-vue and vue sfc? But it need mobx-vue maintainer to maintian different tools to support this feature. (e.g. mobx-vue-loader for webpack, rollup-plugin-mobx-vue for vite and rollup, …etc). Not a reliable choice i think. I didn’t see any api allow us to change the <template> behavior. It’s parsed by @vue/compiler-sfc and no public api.

My opinion

Deprecate vue-class-component and make vue sfc as first class support.

Summary

Any idea and disscussion welcome, maybe you can design the final mobx-vue v3 api.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:9
  • Comments:18 (4 by maintainers)

github_iconTop GitHub Comments

3reactions
sergeydorovskycommented, Aug 12, 2021

I’m currently using MobX 6 with Vue 3. Here is the plugin I wrote (it’s actually Quasar boot file): Works like a charm. Hope this helps.

import { ComponentPublicInstance } from '@vue/runtime-core'
import { Reaction } from 'mobx'
import { boot } from 'quasar/wrappers'

const reactionKey = '__mobx_reaction__'

interface MobxComponent extends ComponentPublicInstance {
  [reactionKey]: Reaction
}

function getComponentName(vm: ComponentPublicInstance) {
  // @ts-ignore
  return (vm.$options.name || vm.tag || '<observed-component>') as string
}

export default boot(({ app }) => {
  app.mixin({
    created(this: MobxComponent) {
      const name = getComponentName(this)
      const reaction = new Reaction(`${name}::mobx-reaction`, () => {
        if (this.$.isMounted) {
          this.$forceUpdate()
        }
      })

      this[reactionKey] = reaction
      // @ts-ignore
      const originalRender = this.$.render

      // @ts-ignore
      this.$.render = function(...args: any) {
        let renderResult: unknown

        reaction.track(() => {
          renderResult = originalRender.call(this, ...args)
        })

        return renderResult
      }
    },
    beforeUnmount(this: MobxComponent) {
      this[reactionKey].dispose()
    },
  })
})
3reactions
steven-sheehycommented, Jun 17, 2021

Please don’t deprecate vue-class-component support. It’s the only reason I use mobx-vue. If you want to support composition API in addition to classes that would be fine. You could release the composition support now and do another release later when vue-class-component finalizes v3 support.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Vue RFC: Expose logic-related component options via ...
There is a lot of FUD in this thread so we need to clarify a bit: - This API is purely additive to...
Read more >
mobx-vue-lite-demo-2 - CodeSandbox
CodeSandbox is an online editor tailored for web applications.
Read more >
mobx-vue - npm
Vue bindings for MobX. Latest version: 2.2.0, last published: a year ago. Start using mobx-vue in your project by running `npm i mobx-vue`....
Read more >
Writing React like Vue 3 - kutlu sahin - Medium
The Vue team has come up with this RFC to address the issues with the current options ... Implementing composition api with React...
Read more >
Adopt a modern JavaScript framework for use with MediaWiki
Vue has an RFC process too, but only one person Evan You decides whether to accept or reject the RFC[3]. [3]: https://github.com/vuejs/rfcs/pulls?q=is%3Apr+is% ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found