在 React JSX 中引用 `this`

Referencing `this` in React JSX

我正在 React JSX 中编写一个函数,其中包含需要与 this

通信的回调
    this.socket.on('addWashedMission', washedMission => {
        console.log('onAddWashedMission - %s - %s', washedMission.name, 
            new Date(washedMission.birthtime));

        this.state.washedMissions.filter(function(o) {
            return o.name === washedMission.name;
        }).forEach(function(element, i, arr) {
            // HERE IT IS //
            this.state.washedMissions.state.washedMissions.slice(
                this.state.washedMissions.state.washedMissions.indexOf(element), 1);
        });

        this.state.washedMissions.push(washedMission);
        this.state.washedMissions.sort(function(a,b) {
            return b.birthtime - a.birthtime;
        });

        this.setState({
            washedMissions: this.state.washedMissions
        });
    });

注意到this.state.washedMissions了吗?当我在那个回调中时,Firefox 脚本调试器告诉我浏览器不知道 this 是什么,因此我不能以这种方式操作我的数组。

如何确保 this 在我的回调范围内——请注意,回调是同步的,所以我不担心任何时间问题。

问题是匿名函数作用域中的 this 没有引用定义它的包含作用域。相反,它将引用分配给它的对象的范围以及稍后调用它的对象。

所以你需要 "trick" 它认为 this 引用你想要的 this

有几种方法可以实现您想要的效果。

  1. 在匿名函数外部使用 var that = this; 定义,并在其中引用它而不是 this 来创建闭包。 (旧浏览器的向后兼容性更好)

    var that = this;
    this.state.washedMissions.filter(function(o) {
        return o.name === washedMission.name;
    }).forEach(function(element, i, arr) {
        // HERE IT IS //
        that.state.washedMissions.state.washedMissions.slice(
            that.state.washedMissions.state.washedMissions.indexOf(element), 1);
    });
    
  2. 将匿名函数的范围绑定到其定义范围的 this,然后再将其传递给 forEach 方法(处理此问题的首选 ECMA5 方法)

    this.state.washedMissions.filter(function(o) {
        return o.name === washedMission.name;
    }).forEach(function(element, i, arr) {
        // HERE IT IS //
        this.state.washedMissions.state.washedMissions.slice(
            this.state.washedMissions.state.washedMissions.indexOf(element), 1);
    }.bind(this));
    

你有

...forEach(function(element, i, arr) {
  this.state.washedMissions.state.washedMissions.slice(
    this.state.washedMissions.state.washedMissions.indexOf(element), 1);
});

您需要提供 thisArg 作为 Array.prototype.forEach

的第二个参数
...forEach(function(element, i, arr) {
  this.state.washedMissions.state.washedMissions.slice(
    this.state.washedMissions.state.washedMissions.indexOf(element), 1);
}, this); // <--- note the `this` after the function() {}

或者你需要一个 arrow function 词法绑定 this

...forEach((element, i, arr) =>
  this.state.washedMissions.state.washedMissions.slice(
    this.state.washedMissions.state.washedMissions.indexOf(element), 1)
);

或者您可以使用其他答案中提供的石器时代慢Function.prototype.bind

为所有函数使用更多箭头函数

this.socket.on('addWashedMission', washedMission => {
    console.log('onAddWashedMission - %s - %s', washedMission.name, 
        new Date(washedMission.birthtime));

    this.state.washedMissions
        .filter(o => {
            return o.name === washedMission.name;
        })
        .forEach((element, i, arr) => {
            const elementIndex = this.state.washedMissions.state.washedMissions.indexOf(element);
            this.state.washedMissions.state.washedMissions.slice(elementIndex, 1);
        });

    this.state.washedMissions.push(washedMission);
    this.state.washedMissions.sort((a,b) => {
        return b.birthtime - a.birthtime;
    });

    this.setState({
        washedMissions: this.state.washedMissions
    });
});