2
votes

After the component is unmounted, I get errors when I resize the window. I know window.removeEventListener is being called, but it is acting as if it never gets called. The error says:

warning.js:36 Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the HeaderMain component.

I even tried using a code example from the React docs, and it does the same thing my class was doing. From https://facebook.github.io/react/tips/dom-event-listeners.html:

import React from "react";

var HeaderMain = React.createClass({
  getInitialState: function() {
    return {windowWidth: window.innerWidth};
  },

  handleResize: function(e) {
    this.setState({windowWidth: window.innerWidth});
  },

  componentDidMount: function() {
    window.addEventListener('resize', this.handleResize);
  },

  componentWillUnmount: function() {
    window.removeEventListener('resize', this.handleResize);
  },

  render: function() {
    return <div>Current window width: {this.state.windowWidth}</div>;
  }
});

module.exports = HeaderMain;

I've tried messing around with bind(), I've tried it in ES6, and tried different versions of React.js. I can't get rid of the error.

How do I make sure my event listener will get removed?

2
This code should run fine. You probably didn't actually paste the code that is demonstrating the problem.Andy Ray
No, I actually did. This code doesn't work, and it's almost identical from the example on the React docs, except for the last line. See my solution below.BBaysinger

2 Answers

3
votes

I figured out that it has to do with binding. When you call .bind(this), it returns a new function with the desired scope, so it wasn't unregistering the same function I thought I added.

Also, I found for whatever reason, in ES6 + React v15.3.1 (latest) the automatic binding doesn't occur (I thought it was supposed to) as it does in ES5 (same version of React), so I just stored a reference to the bound function, and reused it.

import React from "react";

export default class HeaderMain extends React.Component {

  boundFunc = this.handleResize.bind(this);

  constructor()
  {
    super();

    this.state = {height:window.innerHeight + "px"};
  }

  handleResize(e)
  {
    this.setState({height:window.innerHeight + "px"});
  }

  componentDidMount()
  {
     window.addEventListener('resize', this.boundFunc);
  }

  componentWillUnmount()
  {
    window.removeEventListener('resize', this.boundFunc);
  }

  render() {

    return (
      <header class="header_main" style={{height:this.state.height}}>
         Example Header
      </header>
    );
  }
}
0
votes

dont worry about this warning,you can test with a console.log() in handleresize function like this :

 handleResize: function(e) {
    this.setState({windowWidth: window.innerWidth} , function(){
    console.log("windowWidth" , windowWidth);
    });
  }

test it with change route or any action to call componentWillUnmount function and then open your console and resize window.