如何修复“ TypeError:无法读取未定义的属性'注释'”

时间:2019-06-25 17:38:37

标签: reactjs

我正在编写一个计时器来自动更新发布的时间。在没有this._timer的情况下,代码可以很好地工作,并且当我设置计时器时,应用程序被"TypeError: Cannot read property 'comment' of undefined"压缩了。

我尝试使用this._timer = setInterval(this._updateTimeString.bind(this), 3000);而不是this._timer = setInterval(this._updateTimeString, 3000);,它可以工作,但我不知道为什么。

componentWillMount() {
  this._updateTimeString();
  this._timer = setInterval(this._updateTimeString, 3000);
}

_updateTimeString() {
  const now = Date.now();
  const duration = (now - this.props.comment.createdTime) / 1000;
  const timeDuration =
    duration > 60
      ? duration >= 60 * 2
        ? duration > 60 * 60
          ? duration >= 60 * 60 * 2
            ? duration > 60 * 60 * 24
              ? duration > 60 * 60 * 24 * 2
                ? `${Math.round(duration / (60 * 60 * 24))} days ago`
                : `${Math.round(duration / (60 * 60 * 24))} day ago`
              : `${Math.round(duration / (60 * 60))} hours ago`
            : `${Math.round(duration / (60 * 60))} hour ago`
          : `${Math.round(duration / 60)} mins ago`
        : `${Math.round(duration / 60)} min ago`
      : `${Math.round(Math.max(duration, 1))} s ago`;
  this.setState({
    timeString: timeDuration
  });
}

4 个答案:

答案 0 :(得分:2)

您正在调用cotext用户箭头功能:

componentWillMount() {
  this._updateTimeString();
  this._timer = setInterval(() => this._updateTimeString(), 3000);
}

但是首先...嵌套三元是 EVIL 使用其他任何方法...简单的if或类似的东西

function formatTime(duration) {
  switch(true) {
    case duration > 60 * 60 * 24:
      return 'days'
    case duration > 60 * 60:
      return 'hours'
    case duration > 60:
      return 'mins'      
    case duration > 1:
      return 'secs'            
    default:
      return ''
  }  
}

或其他但不嵌套的三元:)

答案 1 :(得分:1)

this未绑定到_updateTimeString中的组件实例。在您的构造函数中,将方法绑定到实例。

class MyComponent extends Component {
    constructor(props) {
        super(props);

        this._updateTimeString = this._updateTimeString.bind(this);
    }
}

如果您不喜欢这种外观,这里有一些alternatives。享受吧!

答案 2 :(得分:0)

您可以使用.bind,但我建议使用arrow functions

只需更改:

_updateTimeString() {

收件人:

_updateTimeString = () => {

答案 3 :(得分:0)

对于您的绑定问题,请查看以下内容:

new class A {
  constructor() {
    setInterval(this.tick, 1000)
    setInterval(() => this.tick(), 1000)
  }

  tick() {
    console.log(this)
  }
}()

区别在于调用的上下文。基本上,通过将this.tick传递到setInterval中,您传递的是指向函数主体本身的指针,而不是指向对象方法的指针,因此在tick() this内部指向setInterval的位置正在执行的是Window对象。

enter image description here

记住JS通过值而不是通过指针传递函数参数-即使该参数是函数,也要通过值传递,即,函数主体不是指针,因此不会复制this得到“复制”的外观:

let A = {
  me: 'A',
  whoAmI: function () { return `I am ${this.me}` }
}

console.log(A.whoAmI())
// prints "I am A"
// so method was invoked inside A context
// ( this points to A )

function someFunction( callback ) {
  return callback()
}

console.log( someFunction(A.whoAmI) )
// "I am undefined"
// so method was invoked out of context
// ( this points to undefined )
// this is because argument passed a function body
// not a method pointer

// to simulate passing argument by pointer
// we have to pass another function that
// invokes A.whoAmI within A context
// we do that by defining new function that actually calls A.whoAmI()
// and pass it over
console.log( someFunction(() => A.whoAmI()) )
// "I am A"

A.whoAmI.bind(A)只是() => A.whoAmI()

的另一种语法形式