Subscribe on changes!

Suggest provide observable api like vue 2.0

avatar
Oct 14th 2020

What problem does this feature solve?

Generally, I use class based object oriented design my application, I use member variable to mange UI state and method to handle UI interaction, after that I just use stateless component to render, the component access state from the store instance through direct import or provide/inject. This has a lot of benefits

  1. Separate state and UI completely and state is quite easy to write and test
  2. Free to use polymorphism/inherit and all design pattern
  3. Share domain model across different project

In Vue 2.0 that works well

import Vue from 'vue'

class CounterStore {
  count = 1
  add = () => {
    this.count ++
  }
}

const store = Vue.observable(new CounterStore())

export default {
  render() {
    return <button onclick={store.add}>{store.count}</button>
  }
}

works well too on react/mobx

import { makeAutoObservable } from 'mobx'
import { observer } from 'mobx-react'

class CounterStore {
  count = 1
  add = () => {
    this.count ++
  }
  constructor () {
    makeAutoObservable(this)
  }
}

const store = new CounterStore()

export default observer(()=> <button onClick={store.add}>{store.count}</button>)

Reactive API is not supported because the return store is a proxy and this is bound to origin object. It's there any possibility to provide an observable API like Vue 2.0?

What does the proposed API look like?

import { observable, defineComponent } from 'vue'

class CounterStore {
  count = 1
  add = () => {
    this.count ++
  }
}

const store = observable(new CounterStore())

export default defineComponent({
  setup () {
    return () => <button onClick={store.add}>{store.count}</button>
  }
})
avatar
Oct 14th 2020
import { ref, reactive, defineComponent } from 'vue'

class CounterStore {
  count = ref(1)
  add = () => {
    this.count.value++
  }
}

const store = reactive(new CounterStore())
export default defineComponent({
  setup () {
    return () => <button onClick={store.add}>{store.count}</button>
  }
})

should work fine.

avatar
Oct 14th 2020

Reactive API is not supported because the return store is a proxy and this is bound to origin object. It's there any possibility to provide an observable API like Vue 2.0?

That partially correct, even though for most use cases, the reactive proxy implementation of Vue 3 works with classes just fine - but yes, there are caveats. In your case, using a proper instance method works fine.

What you ask here would require re-implementing most of the old reactivity code in Vue 3 alongside the new implementation, and that won't happen.

avatar
Oct 29th 2020
import { reactive, defineComponent } from 'vue'

class CounterStore {
  count = 0
  add () {
    this.count++
  }
}

const store = reactive(new CounterStore())

export default defineComponent({
  setup () {
    return () => <button onClick={() => store.add()}>{store.count}</button>
  }
})

works well after remove arrow function