Do autorun and reaction have to be inside the constructor in order to work? Can I write this simple example without constructor?
Also the code that I have inside the autorun runs normally but if I change it to console.log(this.expenses)
it doesn't work. Why is that?
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
autorun and reaction does not have to be in the constructor. You could for example do this if you prefer:
Example
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)
)
The reason why console.log(`${this.expenses}`)
works and console.log(this.expenses)
doesn't is because you are not dereferencing anything in your shallow array when you write this.expenses
.
When you write...
`${this.expenses}`
... you are implicitly calling toString()
on this.expenses
. You can use toJS or slice
to get the same effect when not putting it in a string:
Example (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)