当作用域嵌套在React中时,如何避免在ES6中创建对'this'的引用:const that = this

时间:2019-07-03 09:57:23

标签: javascript reactjs function ecmascript-6 scope

我正在阅读air-bnb javascript样式指南,它说不应这样做:

23.5不要保存对此的引用。使用箭头功能或Function#bind。

// bad
function foo() {
  const self = this;
  return function () {
    console.log(self);
  };
}

// bad
function foo() {
  const that = this;
  return function () {
    console.log(that);
  };
}

// good
function foo() {
  return () => {
    console.log(this);
  };
}

我已经进行了一些研究,并在stackoverflow中找到了两个答案,但是其中一个可以接受的答案是不能绕开它:

ES6 avoid that/self

另一个建议使用绑定,但建议使用生成器函数。

Nested reference to `this` in ES6 classes

我正在构建ReactJS应用,我需要从Firebase Promise中访问setState。

   saveSessionToDB = () => {
        const that = this;
        db.collection("sessions")
          .add({
            props: MyProps
          })
          .then(function(docRef) {
            console.log("Session written with ID: ", docRef.id);
            that.setState({ sessionID: docRef.id });
          })
          .catch(function(error) {
            console.error("Error adding document: ", error);
            that.setState({ sessionError: error });
          });
}

我尝试了

const {setState} = this;

然后

setState({sessionID:docRef.id});

但出现错误。

我尝试将构造函数中的saveSessionToDB绑定到无效,即使它是一个箭头函数。

还有另一种方法吗?还是我应该接受有时候我仍然必须写const that = this的想法?

3 个答案:

答案 0 :(得分:3)

thencatch也必须使用箭头功能:

saveSessionToDB = () => {
  db.collection("sessions")
    .add({ props: MyProps })
    .then((docRef) => {
      console.log("Session written with ID: ", docRef.id);
      this.setState({ sessionID: docRef.id });
    })
    .catch((error) => {
      console.error("Error adding document: ", error);
      this.setState({ sessionError: error });
    });
}

箭头函数之所以有用,是因为它们没有自己的this上下文(或arguments),因此它们从外部词汇中采用this环境。这就是为什么您可以在箭头功能内使用组件的this的原因。

答案 1 :(得分:1)

对内部功能使用箭头功能:

.then(docRef => {
  console.log("Session written with ID: ", docRef.id);
  this.setState({ sessionID: docRef.id });
})
.catch(error => {
  console.error("Error adding document: ", error);
  this.setState({ sessionError: error });
});

或使用bind

.then(function(docRef) {
  console.log("Session written with ID: ", docRef.id);
  that.setState({ sessionID: docRef.id });
}.bind(this))
.catch(function(error) {
  console.error("Error adding document: ", error);
  that.setState({ sessionError: error });
}.bind(this));

答案 2 :(得分:1)

在用于屏幕/组件甚至在(通常在then()方法和catch()的react语法之外)中使用的promise中,通常会发送一个箭头函数(在fetch上下文中没有任何价值),因此请保留外部上下文(在这种情况下为React.Component上下文)。

在您的情况下,只有两个修复程序(箭头功能,以及该功能),一切正常:

saveSessionToDB = () => {
        const that = this;
        db.collection("sessions")
          .add({
            props: MyProps
          })
          .then((docRef) => { // arrow function
            console.log("Session written with ID: ", docRef.id);
            this.setState({ sessionID: docRef.id }); // that => this
          })
          .catch((error) => { // arrow function
            console.error("Error adding document: ", error);
            this.setState({ sessionError: error }); // that => this
          });
}