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:
Store.js:12 Uncaught TypeError: Cannot set property 'me' of null
My store:
import { observable } from 'mobx';
class Store {
@observable me;
constructor() {
this.me = 'test';
}
change_me(){
this.me = 'test 1';
console.log(this); // null???
}
}
const store = new Store();
export default store;
The component:
import React from "react";
import { observer } from 'mobx-react';
export default class Layout extends React.Component{
render(){
var store = this.props.store;
return(
<div>
<button onClick={store.change_me}>{store.me}</button>
</div>
)
}
}
I've probably missed some fundamental part of how this works, but can't figure it out.
I don't know
mobx
butonClick={store.change_me}
is a problem because you are using a method on a class as a function (withoutthis
). You will have to use use something like:otherwise the binding to
store
is lost.Also possible but less readable:
Yes react execute event callbacks with
this
being null. Since you only give theonClick
callback thechange_me
method and not thestore
as context.Solutions
You have to set the
this
context yourself. you can do this in the following waysbad practices:
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:You can also use the bind method:
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.Good practices
mobx provides a
action.bound
which wraps the function with the proper this context:Alternatively es6 class definition allows you to define the this context properly yourself:
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 theconstructor
so that thethis
context variable always matches the instance of the class.so that:
As @Sulthan mentioned, you need to have the method wrapped by another function
onClick={()=>store.changeMe()}
. Second issue is you are missingaction
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 issueimport {action} from 'mobx
,