MobX 自动运行和构造函数内部的反应

MobX autorun and reaction inside constructor

autorunreaction 必须在 constructor 内部才能工作吗? 我可以在没有 constructor 的情况下编写这个简单的示例吗?

另外,我在 autorun 中的代码运行正常,但如果我将其更改为 console.log(this.expenses),它就不起作用。这是为什么?

import { observable, action, computed, useStrict, autorun, reaction } from 'mobx'
useStrict(true)

class ExpensesStore {

  @observable.shallow expenses = []

  @action addExpense = (expense) => {
   this.expenses.push(expense)
  }

  @computed get getExpense() {
    if(this.expenses.length > 0) {
      return `This is computed from ${this.expenses[0] + this.expenses[1]}`
    }

  }


  constructor() {
    autorun(() => {
      console.log(`${this.expenses}`)
    })

    reaction(
      ()=>this.expenses.map(expense => expense), expense => console.log(expense)
    )
  }


}

const store = window.store= new ExpensesStore()

export default store

autorunreaction 不必在构造函数中。例如,如果您愿意,可以这样做:

例子

class ExpensesStore {
  @observable.shallow expenses = []

  @action addExpense = (expense) => {
   this.expenses.push(expense)
  }

  @computed get getExpense() {
    if(this.expenses.length > 0) {
      return `This is computed from ${this.expenses[0] + this.expenses[1]}`
    }
  }
}

const store = new ExpensesStore()

autorun(() => {
  console.log(`${store.expenses}`)
})

reaction(
  () => store.expenses.map(expense => expense), expense => console.log(expense)
)

console.log(`${this.expenses}`) 有效而 console.log(this.expenses) 无效的原因是,当您编写 this.expenses 时,您没有取消引用浅数组中的任何内容。

当你写...

`${this.expenses}`

...您在 this.expenses 上隐式调用 toString()。你可以使用 toJSslice 在不将其放入字符串中时获得相同的效果:

示例 (JSBin)

class ExpensesStore {
  @observable.shallow expenses = []

  @action addExpense = (expense) => {
   this.expenses.push(expense)
  }

  @computed get getExpense() {
    if(this.expenses.length > 0) {
      return `This is computed from ${this.expenses[0] + this.expenses[1]}`
    }
  }
}

const store = new ExpensesStore()

autorun(() => {
  // store.expenses.slice() works just as well
  console.log(toJS(store.expenses))
})

reaction(
  () => store.expenses.map(expense => expense), expense => console.log(expense)
)

setTimeout(() => {
  store.addExpense(1000)
}, 1000)