【问题标题】:React + Mobx: 'this' is null when trying to update storeReact + Mobx:尝试更新商店时“this”为空
【发布时间】:2016-11-20 08:22:08
【问题描述】:

刚开始使用 Mobx 和 React,无法更新商店。单击按钮时出现错误,该按钮应更新“我”属性:

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>
        )

    }
}

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

【问题讨论】:

    标签: reactjs mobx mobx-react


    【解决方案1】:

    是的,在 this 为空的情况下响应执行事件回调。因为您只给onClick 回调提供change_me 方法而不是store 作为上下文。

    解决方案

    您必须自己设置this 上下文。您可以通过以下方式做到这一点

    不良做法:

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

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

    您也可以使用bind 方法:

    <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'
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

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

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

        否则与store 的绑定将丢失。

        也可以,但可读性较差:

        onClick={store.changeMe.bind(store)}
        

        【讨论】:

        • 感谢您的输入 - 我已将其分离为组件内的一个函数。但是现在我遇到了另一个问题 - 一旦商店更新,组件就不会重新渲染。如果您想看看stackoverflow.com/questions/40702409/…,我在这里创建了另一个问题。我觉得我快疯了。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-10
        • 1970-01-01
        • 2018-09-20
        • 2023-04-01
        • 2019-11-20
        • 1970-01-01
        相关资源
        最近更新 更多