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';
}
Другие вопросы по тегам