10

刚开始使用 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>
        )

    }
}

我可能错过了它如何工作的一些基本部分,但无法弄清楚。

4

3 回答 3

8

是的,将执行事件回调设为thisnull。因为你只给onClick回调change_me方法而不是storeas 上下文。

解决方案

您必须自己设置this上下文。您可以通过以下方式执行此操作

不良做法:

正如@Eduard 所说,您可以将其变形为箭头功能。箭头函数确保this上下文在函数体中保持不变:

<button onClick={() =>store.change_me()}>{store.me}</button> 

您还可以使用绑定方法:

<button onClick={store.change_me.bind(store)}>{store.me}</button>

这基本上是同样的事情。

为什么他们的做法不好?每次render()调用时,都会重新创建这些方法。并且可能导致额外的不必要的重新渲染。

良好做法

mobx 提供了一个action.bound用正确的 this 上下文包装函数的方法:

@mobx.action.bound
change_me(){
    this.me = 'test 1';
}

或者,es6 类定义允许您自己正确定义 this 上下文:

@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'
于 2018-05-14T11:42:57.477 回答
1

正如@Sulthan 提到的,您需要将方法包装在另一个函数onClick={()=>store.changeMe()}中。第二个问题是您缺少action更新值的方法的装饰器。Mobx 的工作方式是,每个更新属性的方法都需要用@action. 所以下面将解决这个问题import {action} from 'mobx

@action change_me(){
    this.me = 'test 1';
}
于 2017-04-27T06:27:44.507 回答
1

我不知道mobx,但这onClick={store.change_me}是一个问题,因为您将类上的方法用作函数(没有this)。您将不得不使用类似的东西:

onClick={event => store.changeMe(event)}

否则绑定将store丢失。

也可能但可读性较差:

onClick={store.changeMe.bind(store)}
于 2016-11-20T08:30:24.293 回答