Just getting started with Mobx & React and having trouble getting the store to update. I get error when clicking the button, which should update the \'me\' property:
<Yes react execute event callbacks with this
being null. Since you only give the onClick
callback the change_me
method and not the store
as context.
You have to set the this
context yourself. you can do this in the following ways
as @Eduard said you can warp it into an arrow function. the Arrow function makes sure the this
context stays the same in the function body:
<button onClick={() =>store.change_me()}>{store.me}</button>
You can also use the bind method:
<button onClick={store.change_me.bind(store)}>{store.me}</button>
this does basically the same thing.
Why are they bad practises? on every render()
call, these methods are re-created. and can result in extra unnecessary re-renders.
mobx provides a action.bound
which wraps the function with the proper this context:
@mobx.action.bound
change_me(){
this.me = 'test 1';
}
Alternatively es6 class definition allows you to define the this context properly yourself:
@mobx.action
change_me = () => {
this.me = 'test 1';
}
See the arrow function. behind the scenes: instead of defining the function/method on the prototype of the Store
class. the method is created in the constructor
so that the this
context variable always matches the instance of the class.
so that:
var a = new Store(); // a.me = 'test'
var b = new Store(); // b.me = 'test'
a.change_me = b.change_me; // change_me function contains its own this context.
a.change_me(); // a.me = 'test' b.me = 'test 1'
I don't know mobx
but onClick={store.change_me}
is a problem because you are using a method on a class as a function (without this
). You will have to use use something like:
onClick={event => store.changeMe(event)}
otherwise the binding to store
is lost.
Also possible but less readable:
onClick={store.changeMe.bind(store)}
As @Sulthan mentioned, you need to have the method wrapped by another function onClick={()=>store.changeMe()}
.
Second issue is you are missing action
decorator for the method which updating the value. Mobx works in a way where every method which will update properties, it need to be decorated by @action
. So following will fix the issue import {action} from 'mobx
,
@action change_me(){
this.me = 'test 1';
}