简体   繁体   中英

Cannot read property of setState of undefined REACT

I'm trying to set the state of my FileList component, but I keep getting an error

Unhandled Rejection (TypeError): Cannot read property 'setState' of undefined from line 43 - this.setState({list: entries});

I've bound the function to this, as suggested online, does anyone know how to get this to work

 export default class FileList extends Component {
  constructor(props) {
    super(props);
    this.getList = this.getList.bind(this);
    this.renderFiles = this.renderFiles.bind(this);
    this.state = {
    zipFile: props.zipFile,
    uploadPressed: props.uploadPressed,
    list: []
    }
  }

  getList() {
    var entries = new Array;
      let zip = new JSZip(); 
      JSZip.loadAsync(this.state.zipFile).then(function (zip) {
        zip.forEach(function (zipEntry) {
          if(zipEntry.split('/')[1] === "color"){
            if(zipEntry.endsWith('.png')) {
              entries.push(zipEntry.split('/').pop());
            } else if (zipEntry.endsWith('/')) {
            } else {
            }
          } else if(zipEntry.split('/')[1] === "mono") {
            if(zipEntry.endsWith('.png')) {
              entries.push(zipEntry.split('/').pop());
            } else if (zipEntry.endsWith('/')) {
            } else {
            }
          } else if(zipEntry.endsWith('.sslt')) {
          } else {
          }
        });
        alert(entries[0]);
        this.setState({list: entries});
      });
  }

  render() {
    return <div className="file-list">
              <div className="list-zip" >
                <div className="list-zip-name">
                  {this.state.zipFile.name}
                </div>
                <div className="list-zip-size">
                  {this.state.zipFile.size} Bytes
                </div>
                <div className="list-zip-x" >
                  <button className="x-button" onClick={close}>X</button>
                </div>
              </div>
              <hr className="hr"/>
            {this.renderFiles()}
          </div>
  }

  renderFiles() {
    if(this.state.uploadPressed === true) {
    this.getList();
    return <File fileName={this.state.list[0]} />
    }
  }
}

Change your callback functions with arrow ones:

....
JSZip.loadAsync(this.state.zipFile).then( zip => {
zip.forEach( zipEntry => {
    if(zipEntry.split('/')[1] === "color"){
...

You have a .bind for your main function but inside this function you are using regular callback functions for .then and forEach methods. Those functions create their own scope and you are loosing this . With arrow functions you won't loose this ' scope.

Bonus info: You can use an arrow function for your getList function also. With this way you won't need to bind it in your constructor.

A part from the fact that you should be using arrow functions to avoid loosing the current context as already reported by other users you have another error that will raise as soon as you fix the previous.

you're calling setState inside the render method, this will create an infinite loop, to avoid it just put the getList method inside the componentDidMount hook

This is a scoping problem. Your callback function doesn't have access to the component's this . You need to use .bind(this) or an arrow operator ( () => {} ) to access this within your function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM