React + Mobx: 'this' является нулевым при попытке обновить магазин
Просто начинаю работать с Mobx & React и у меня возникают проблемы с обновлением магазина. Я получаю ошибку при нажатии кнопки, которая должна обновить свойство 'me':
Store.js:12 Uncaught TypeError: Cannot set property 'me' of null
Мой магазин:
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;
Компонент:
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>
)
}
}
Я, вероятно, пропустил некоторую фундаментальную часть того, как это работает, но не могу понять это.
3 ответа
Да, реагировать на вызовы события execute this
быть нулевым Так как вы даете только onClick
перезвонить change_me
метод, а не store
как контекст.
Решения
Вы должны установить this
контекст себя. Вы можете сделать это следующими способами
плохие практики:
как сказал @Eduard, вы можете превратить его в функцию стрелки. функция Arrow обеспечивает this
контекст остается неизменным в теле функции:
<button onClick={() =>store.change_me()}>{store.me}</button>
Вы также можете использовать метод связывания:
<button onClick={store.change_me.bind(store)}>{store.me}</button>
это в основном то же самое.
Почему они плохие практики? на каждом render()
вызов, эти методы воссозданы. и может привести к дополнительным ненужным повторным визуализациям.
Хорошая практика
MOBX обеспечивает action.bound
который оборачивает функцию соответствующим контекстом:
@mobx.action.bound
change_me(){
this.me = 'test 1';
}
В качестве альтернативы определение класса es6 позволяет вам правильно определить этот контекст:
@mobx.action
change_me = () => {
this.me = 'test 1';
}
Смотрите функцию стрелки. за кулисами: вместо определения функции / метода на прототипе Store
учебный класс. метод создается в constructor
таким образом this
Переменная контекста всегда соответствует экземпляру класса.
чтобы:
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'
Я не знаю mobx
но onClick={store.change_me}
является проблемой, потому что вы используете метод класса в качестве функции (без this
). Вам придется использовать что-то вроде:
onClick={event => store.changeMe(event)}
в противном случае привязка к store
потерян.
Также возможно, но менее читабельно:
onClick={store.changeMe.bind(store)}
Как уже упоминалось @Sulthan, вам нужно обернуть метод другой функцией onClick={()=>store.changeMe()}
, Вторая проблема - ты пропал action
декоратор для метода, который обновляет значение. Mobx работает таким образом, что каждый метод, который будет обновлять свойства, должен быть украшен @action
, Таким образом, следующие исправят проблему import {action} from 'mobx
,
@action change_me(){
this.me = 'test 1';
}