javascript - ES6 与 React,无法 setState - 'Cannot read property ' setState' of undefined'?

标签 javascript reactjs ecmascript-6

我正在编写针对 ES5 的 React 拖放教程,但我正在使用 ES6。

这是我的代码:

  class Song extends React.Component{
    constructor(props){
      super(props);
      this.state = {isPlaying:false,dragMode:editMode == 1 ? true : false,eligibleToDrag: false};
      //this.dragStart = this.dragStart.bind(this);
    }

    _clickAction(){

      if(this.state.dragMode == false){
        changeSong(this.props.arrIndex); 
        playSong();
      }
    }

    dragStart(e){
      Array.prototype.forEach.call(document.getElementById('screen2').getElementsByClassName('track'),function(e1){
        if(e1.getAttribute('data-songid') == e.currentTarget.getAttribute('data-songid')){
          this.setState({eligibleToDrag: false});
          console.log('ELIGIBLE?',this.state.eligibleToDrag);

        }
        else{
          this.setState({eligibleToDrag: true});
          console.log('ELIGIBLE?',this.state.eligibleToDrag);
        }
      });
      console.log(this.state.eligibleToDrag);
      if(e.currentTarget.parentElement.parentElement.id=="screen"){
        e.dataTransfer.effectAllowed = 'link';
      }
      if(e.currentTarget.parentElement.parentElement.id=="screen2"){
        e.dataTransfer.effectAllowed = 'move';
      }
      draggedObject = e.currentTarget;
      e.dataTransfer.setData("text/html",e.currentTarget);
    }

    dragEnd(e){

    }

    dragOver(e){
      e.preventDefault();
      var relY = e.clientY - e.target.offsetTop;
      var height = e.target.offsetHeight / 2;
      if(e.target.parentNode.parentNode.id == 'screen2'){
        if(relY > height){
          e.target.parentNode.insertBefore(draggedObject,e.target.nextElementSibling);
        }
        else if(relY < height){
          e.target.parentNode.insertBefore(draggedObject,e.target);
        }
      }
      if(e.target.parentNode.parentNode.id == 'screen' && draggedObject.parentNode && draggedObject.parentNode.parentNode.id == 'screen2'){
        draggedObject.remove();
        //e.stopPropagation();
      }
      return;

    }
    render(){
      var isDragMode = this.state.dragMode == true;
      if(isDragMode){
        document.getElementById('screen').classList.add("drag");
        document.getElementById('screen2').classList.add("drag");
      }

      return <div data-songid={this.props.trackInfo.Id} onClick={this._clickAction.bind(this)} className={"track"} draggable={isDragMode ?  "true": "false"} onDragEnd={isDragMode ? this.dragEnd.bind(this) : ''} onDragOver={isDragMode ? this.dragOver.bind(this) : ''} onDragStart={isDragMode ? this.dragStart.bind(this) : ''}>
        <span draggable={"false"}>{this.props.trackInfo.Title}</span><br draggable={"false"} />
        <span draggable={"false"}><i draggable={"false"}>{this.props.trackInfo.Artist}</i></span>
      </div>
    }

  }

在我在dragStart(e)上添加Array.prototype.forEach.call部分之前,该类一直有效。然后它开始在控制台中向我显示“无法读取未定义的属性‘setState’”,指向该部分。我不确定我错过了什么,因为据我所知,我已经在渲染方法中绑定(bind)了所有内容。我的猜测是我还没有绑定(bind)所有内容,但我不确定还能做什么。

最佳答案

原因是在您的 forEach 调用中,变量 this 不再引用您期望的内容。如果您坚持以当前方式执行此操作,则应该在更高的位置声明初始 this 变量并在 forEach 函数中引用它:

...
dragStart(e){
  var context = this;
  Array.prototype.forEach.call(document.getElementById('screen2').getElementsByClassName('track'),function(e1){
    if(e1.getAttribute('data-songid') == e.currentTarget.getAttribute('data-songid')){
      context.setState({eligibleToDrag: false}); //change this -> context
      console.log('ELIGIBLE?',context.state.eligibleToDrag);

    }
    else{
      context.setState({eligibleToDrag: true});
      console.log('ELIGIBLE?',context.state.eligibleToDrag);
    }
  });
...

但是,由于您使用的是 ES6,您可以使用 Shiny,New,Fat Arrow Function .

...
dragStart(e) {
  Array.prototype.forEach.call(document.getElementById('screen2').getElementsByClassName('track'), e1 => {
    //use `this` as per usual
  }
}

上述情况是可能的,因为 ES6 箭头函数捕获封闭上下文的 this

编辑

根据 dandavis 提到的内容,您实际上可以在 forEach 的回调函数中设置 this 的值。它是 forEach 函数的最后一个参数。因此,如果 OP 想要以最快的方式解决这个问题,他只需将 this 附加到他的 forEach 调用的最后一个参数,它就会像魔术一样工作。

Array.prototype.forEach.call(document.getElementById('screen2').getElementsByClassName('track'), function(e1){
  //As per usual
},this);

关于javascript - ES6 与 React,无法 setState - 'Cannot read property ' setState' of undefined'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34710927/

相关文章:

javascript - 如何在回调中在 redux-saga 中返回 "yield put"?

javascript - 为什么 Segment.io 加载程序脚本将方法名称/参数推送到一个看似被覆盖的队列中?

javascript - Twitter Bootstrap 隐藏水平滚动

javascript - React-Leaflet Map 不更新

javascript - 如何在两个数字之间进行 array.map

javascript - node.js(ES6/Babel)中 import X 和 import * as X 的区别?

javascript - 这个 JQuery 有什么问题?

javascript - 在 jquery 循环中生成多个 div

javascript - 如何知道 react 传单弹出窗口何时关闭

javascript - 如何防止在密码输入字段中输入空格/空白 | ReactJs