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.
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'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With