I just playground with some code with mobX, and this happened, don't know why but i'm sure it not much different from offical docs
Here is store.tsx
import { observable, computed, action, makeObservable, override, makeAutoObservable } from "mobx"
class CounterStore {
initValue = 0
powValue = Math.pow(this.initValue, 2)
constructor() {
makeAutoObservable(this)
}
increaseNumber() {
this.initValue = this.initValue + 1
}
}
const Store = new CounterStore()
export default Store
Here is where i use this. called increasement.tsx
import { observer } from "mobx-react"
export const IncrementButton = observer(({ store }) => {
return (
<div>
<button onClick={store.increaseNumber}>Increase</button>
<h1>{store.initValue}</h1>
</div>
)
})
And index.tsx
ReactDOM.render(
<React.StrictMode>
<IncrementButton store={Store} />
{/* <TestUseState /> */}
{/* <TestEffect />
<UseMemoTest /> */}
</React.StrictMode>,
document.getElementById("root"),
Weird is, it show initValue
, but when i click increase it show can't not read properties
Please help, thanks
as @mimoid noticed, your method is not bound to the class and losing context (this
). It is not MobX problem, it is just regular javascript feature called late binding.
Although you don't really need to change makeAutoObservable
to makeObservable
, you can just use arrow functions, in my opinion it is more "native" way:
class CounterStore {
initValue = 0
powValue = Math.pow(this.initValue, 2)
constructor() {
makeAutoObservable(this)
}
// Just make it an arrow function
increaseNumber = () => {
this.initValue = this.initValue + 1
}
}
Alternatively you can pass autoBind
option to the makeAutoObservable
:
autoBind: true uses action.bound/flow.bound by default, rather than action/flow. Does not affect explicitly annotated members.