【问题标题】:Why 'this' is undefined inside a Promise call为什么在 Promise 调用中未定义“this”
【发布时间】:2018-11-17 17:27:54
【问题描述】:

我不明白发生了什么

componentDidMount() {
    console.log('componentDidMount');
    //const self = this; 
    let _id = this.props.match.params.id.toUpperCase();

    if (_id != this.state.id.toUpperCase()) {

        axios.get('/data/pricemultifull?fsyms=' + _id + '&tsyms=USD')
            .then(response => {
                // let _currentcoin = { ...resp.data.RAW.BTC.USD, ticker: _id };
                this.setState({ id: _id }); //this == undefined
            });
    }
}

我可以得到回复,但this 始终未定义,我无法回复setState。我正在使用一个箭头函数,我认为它是组件级别的“this”范围。在我提出请求之前,我可以通过创建一个新的 var 并设置 'this' 来修复它。我知道this 应该可以工作。我错过了什么?

我的整个组件

import React, { Component } from 'react';
import axios from '../../axios';


class CoinViewer extends Component {

state = {
    coin: {},
    hasLoaded: false,
    id: ''
}

componentDidMount() {
    console.log('componentDidMount');
    //const self = this; 
    let _id = this.props.match.params.id.toUpperCase();

    if (_id != this.state.id.toUpperCase()) {

        axios.get('/data/pricemultifull?fsyms=' + _id + '&tsyms=USD')
            .then( resp => {
                // let _currentcoin = { ...resp.data.RAW.BTC.USD, ticker: _id };
                this.setState({ id: _id });
            });
    }
}

componentWillMount() {

}

componentWillUpdate() {


}

componentDidUpdate() {

}

getCompleteCoinData(_id) {

}


render() {


    return (
        <div>
            CoinViewer Component: {this.state.id} sads
        </div>
    )
}

}

导出默认的 CoinViewer

【问题讨论】:

  • 我使用相同的方法,但使用了 fetch。它似乎正在工作!
  • 您应该能够使用箭头函数访问组件的this 上下文。见这里:stackoverflow.com/questions/41194866/…你能分享你整个组件的代码吗?
  • 无法重现您的问题,我尝试了与您的代码类似的方法,但它对我有用。 codepen.io/smilesaayush/pen/VdKoJa 如果我在 axios 响应后不使用箭头函数,那么它会报错,否则它可以工作。
  • 如果我声明 let self == this 然后 self.setState(...) 它可以工作。对于任何其他公理承诺,我从来不需要这样做。对我来说有点困惑
  • 也许可以尝试在每个步骤中记录this 的内容,看看是否符合您的预期。还要验证你是否能够在代码的其他地方使用箭头函数,这样你就知道它不是编译器错误

标签: javascript reactjs


【解决方案1】:

:编辑 哇,以下内容有点正确,但真正的问题是您没有初始化状态。 https://reactjs.org/docs/react-component.html#constructor

constructor() {
  super();
  this.state = {
    coin: {},
    hasLoaded: false,
    id: ''
  }
}

您可以像这样使用词法范围和修复,这是保护this 的流行模式。

基本上,当您使用来自其他库/API 的 Promise 或函数时,您不知道它们在回调函数中将其上下文设置为什么。

为了使用您想要的上下文,您将需要保存的上下文保存在范围内的变量中并在那里引用它_this,而不是通过指向上下文this。我建议阅读“you dont know js”以进一步理解这个概念。

componentDidMount() {
  console.log('componentDidMount');
  const _this = this; 
  let _id = _this.props.match.params.id.toUpperCase();

  if ( _id != _this.state.id.toUpperCase() ) {
    axios.get('/data/pricemultifull?fsyms=' + _id + '&tsyms=USD')
      .then(response => {
        _this.setState({ id: _id }); //this == undefined
      });
  }
}

【讨论】:

  • 我要补充一点,this 不是变量。关闭不适用于它。另外,我更喜欢const that = this :-)
  • 箭头函数根据定义明确保留this的词法范围,因此在传递给then的回调函数内部,_this === this应该为真。问题来自其他地方(可能是一个糟糕的转译器?)。
  • @JohnWeisz:我希望this 至少是axios。为什么你认为它应该有效?
  • @RaphaMex 这是因为它在参数字段中创建了一个匿名函数,因此词法范围为componentDidMount
  • 这就是我所采用的,它奏效了。似乎 _this 的声明是无关紧要的 const _this = this; _this.setState({ id: _id })
【解决方案2】:

解决方案 1:箭头函数..

requestSuccess = (resp) => {
  // let _currentcoin = { ...resp.data.RAW.BTC.USD, ticker: _id };
  this.setState({ id: _id });
}

componentDidMount() {
  console.log('componentDidMount');
  //const self = this; 
  let _id = this.props.match.params.id.toUpperCase();
  if (_id != this.state.id.toUpperCase()) {
     axios.get('/data/pricemultifull?fsyms=' + _id + '&tsyms=USD')
       .then(this.requestSuccess);
  }
}

解决方案 2:绑定

componentDidMount() {
  console.log('componentDidMount');
  //const self = this; 
  let _id = this.props.match.params.id.toUpperCase();
  if (_id != this.state.id.toUpperCase()) {
     axios.get('/data/pricemultifull?fsyms=' + _id + '&tsyms=USD')
       .then((resp) => {
          // let _currentcoin = { ...resp.data.RAW.BTC.USD, ticker: _id };
          this.setState({ id: _id });
     }.bind(this));
  }
}

【讨论】:

    【解决方案3】:

    在使用 React.js 时,您可能会遇到一个问题: 从 promise 内部访问 this。解决这个引用的解决方案不止一种 承诺。旧的方法是设置 self = this 参考虽然这可行,但推荐的解决方案是 更符合 ES6 的内联,将在此处使用箭头函数:

    class Component extends React.Component { 
      componentDidMount() {
        let component = this;
        axios.get('http://…').then(function(data) {
          component.setState( { name: data.blah } );
        });
      }
    }
    

    如上所述,箭头语法是一种更智能的方式来允许使用 正如我们所看到的,这是对 React.Component 类的引用 下面:

    class Component extends React.Component { 
      componentDidMount() {
        axios.get('http://…').then(data => {
          this.setState( { name: data.blah } );
        });
      }
    }
    

    请注意,而不是使用 函数(数据){ //body }, 我们使用了 data => { //body },在这种情况下,这个引用不会取回 Promise 实例。

    【讨论】:

      猜你喜欢
      • 2016-04-28
      • 2018-08-17
      • 2018-07-18
      • 1970-01-01
      相关资源
      最近更新 更多