在React.js中使用异步回调函数时无法读取状态

时间:2019-04-06 03:46:24

标签: javascript reactjs

所以我从这里的stackoverflow复制了此函数,我的目标是能够在注册后和移至其他路由之前立即更新数据库和配置文件信息,结果符合我的预期,但是我可以不再访问回调中的状态,请有人可以帮助我调试此代码:

  signup = (e) => {
    this.setState({ loading: true });
    e.preventDefault();
    fire.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
      .then((userCredentials) => {
        if (userCredentials.user) {
          userCredentials.user.updateProfile({
            displayName: this.state.username,
            photoURL: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdVmHPt9SajdsWlAZWzqRXkd-SzmmO9bBUV45fLnw5giijsty3OA',
          }).then((s) => {
            fire.database()
              .ref(`master/${userCredentials.user.displayName}/setup/`)
              .update({
                bio: 'Be original',
              })
              .then(() => {
                window.location.reload();
              });
          })
        }
      })
      .catch(function (error) {
        console.log(error);
        this.setState({ signupError: true, loading: false, });
      });
  }

错误发生在catch(错误)

  

TypeError:无法读取未定义的属性'setState'

我怀疑此问题来自使用多个.then

2 个答案:

答案 0 :(得分:1)

JS函数具有自己的this上下文。

在您的情况下,您可以在回调中使用this上下文。 react组件的this上下文将在回调内丢失。这就是为什么catch块无法识别setState方法

的原因

要在回调内部保留和使用this上下文,请将this分配给local variable (named the variable as self in below example)并在回调内部访问它。

  signup = (e) => {
        var self= this;
        this.setState({ loading: true });
        e.preventDefault();
        fire.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
          .then((userCredentials) => {
            if (userCredentials.user) {
              userCredentials.user.updateProfile({
                displayName: this.state.username,
                photoURL: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdVmHPt9SajdsWlAZWzqRXkd-SzmmO9bBUV45fLnw5giijsty3OA',
              }).then((s) => {
                fire.database()
                  .ref(`master/${userCredentials.user.displayName}/setup/`)
                  .update({
                    bio: 'Be original',
                  })
                  .then(() => {
                    window.location.reload();
                  });
              })
            }
          })
          .catch(function (error) {
            console.log(error);
            self.setState({ signupError: true, loading: false, });
          });
      }

您还可以使用arrow functionsarrow functions没有自己的this上下文,因此您将能够访问外部望远镜的this上下文

.catch((error)=> {
   console.log(error);
   this.setState({ signupError: true, loading: false, });
});

答案 1 :(得分:1)

this中的

catch不是您的课程,请参见普通函数和箭头函数之间的区别。有两种方法可以解决您的问题。

  • 首先:使用箭头功能
.catch(function (error) {
  console.log(error);
  this.setState({ signupError: true, loading: false, });
});
  • 第二:为self设置本地this
signup = (e) => {
  this.setState({ loading: true });
  e.preventDefault();
  const self = this; // It can be what ever you want, `self` is the most popular
  ...
}

然后

.catch(function (error) {
  console.log(error);
  self.setState({ signupError: true, loading: false, });
});