无法在本机函数中读取 "this"

cannot read "this" in react native function

我正在尝试设置来自 facebook 登录的用户数据并将其存储在一个状态中,但出现错误。

Facebook 身份验证

_fbAuth(){
  LoginManager.logInWithReadPermissions(['public_profile']).then(function(res){
    if(res.isCancelled){
      console.log('login cancelled.')
    } else {
      AccessToken.getCurrentAccessToken().then(tokenData => {
        if(tokenData) {
          const { accessToken, userID } = tokenData;
          fetch('https://graph.facebook.com/v2.5/me?fields=email,name,friends&access_token=' + accessToken).then((response) => 
            response.json()).then((json) => {
              this.setState({ user_email: json.email })
            }).catch(() => {
              reject('ERROR GETTING DATA FROM FACEBOOK')
            }
          )
        }
      })
    }
  }, function(err){
    console.log(err)
  })
}

将数据注册到引发此错误的状态:

[TypeError: undefined is not a function (evaluating '_this3.setState({ user_email: json.email })')]

我应该如何在 fetch() 响应中访问 this

原因是 this 由于嵌套箭头函数而丢失。您定义一个变量来保存对 this 的引用,并使用 that 代替。

您可以通过在函数中执行以下操作来解决它

_fbAuth = () => {
  const that = this;
  ...
  that.setState({ user_email: json.emal });
  ...
}

您还应确保已通过将函数设为箭头函数或在构造函数中将其绑定来绑定函数。

在您的构造函数中添加这一行以将组件上下文绑定到函数范围。

this._fbAuth = this._fbAuth.bind(this);

这应该有效!

不要使用 bind 或旧的 const that = this 解决方法。如果你完全切换到箭头函数,这会容易得多,我建议也使用 async/await。例如:

_fbAuth = async () => {
    try {
        let resLogin = await LoginManager.logInWithReadPermissions(['public_profile', 'email', 'user_friends']);
        if(resLogin.isCancelled){
            console.log('login cancelled.');
            return;
        }
        let resTokenData = await AccessToken.getCurrentAccessToken();
        if(resTokenData) {
            const {accessToken, userID} = resTokenData;
            let resAPI = await fetch(`https://graph.facebook.com/v2.5/me?fields=email,name,friends&access_token=${accessToken}`);
            resAPI = resAPI.json();
            this.setState({user_email: resAPI.email});
        }
    } catch (err) {
        console.log(err);
    }
};

避免使用 "callback hell",使用 async/await 看起来更清晰易读。应该与 LoginManager 一起工作,因为它似乎 return 一个承诺。我还在示例中添加了模板字符串,并在用户取消时添加了 return。没有必要以这种方式缩进整个 else 块。

顺便说一句,您正在尝试通过 API 获取电子邮件和好友,但您并未请求权限,这是故意的吗?我已经添加了权限。

_fbAuth(){

const _this = this;  // add this line

  LoginManager.logInWithReadPermissions(['public_profile']).then(function(res){
    if(res.isCancelled){
      console.log('login cancelled.')
    } else {
      AccessToken.getCurrentAccessToken().then(tokenData => {
        if(tokenData) {
          const { accessToken, userID } = tokenData;
          fetch('https://graph.facebook.com/v2.5/me?fields=email,name,friends&access_token=' + accessToken).then((response) => 
            response.json()).then((json) => {
              _this .setState({ user_email: json.email }) // replace this with _this
            }).catch(() => {
              reject('ERROR GETTING DATA FROM FACEBOOK')
            }
          )
        }
      })
    }
  }, function(err){
    console.log(err)
  })
}