[SOLVED] Calling setState() on unmounted component


#1

I’m new to Meteor and React, and have come across some odd behaviour that I cannot explain. I have a component that is created with state by a constructor. This component displays a list of items. I’ve implemented a basic infinite scroll by detecting when the window has been scrolled to the bottom, at which point I increment the state value (which is a limit on the publication for the list of items).

export default class Component extends TrackerReact(Component) {

  constructor(props) {
    super(props)

    this.state = {
      infNumber: 5
    }
  }

  componentDidMount() {
    window.addEventListener('scroll', this.handleScroll.bind(this));
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll.bind(this));
  }

  handleScroll(event) {
    if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
      let showing = this.state.infNumber;
      this.setState({
        infNumber: showing + 5
      })
    }
  }

  shops() {
    return Collection.find({}).fetch();
  }

  render() {

    let searchQuery = this.props.query? this.props.query: "";

    Meteor.subscribe('collection', searchQuery, this.state.infNumber);

    let shops = this.shops().map(shop => {
      return <ChildComp key={shop._id} shop={shop} />
    })

    return (
      <div>
        {shops}
      </div>
    )
  }
}

All works fine, except that when I navigate away from this route, and then back to it (without using browser back), I get an error when I scroll to the bottom of the page:

“setState can only update a mounted or mounting components… This usually means you have called setState() on an unmounted component”

It actually works fine, so the error may be an unintentional byproduct of the Meteor/React integration however I want to be sure.

This component is rendered in another route (Route2). When I visit that route I get the same issue, but curiously every time I visit a route with this component, the error count increases -

Route1 - 1st visit: No issues;
Route 2 - 1st visit: Error when scrolling to bottom;
Route 1 - 2nd visit: 2 errors per scroll to bottom;
Route 2 - 2nd visit: 3 errors per scroll to bottom;
.
.
.
Any ideas what I’m missing?

EDIT: I am getting the error on every page, even ones without the component in question… Could it be due to the way I’ve added the event listener?

SOLVED: Turns out adding a .bind(this) to a function creates a new function reference, so the listener was never being removed. Can be overcome by binding and reassigning the function in the constructor, then calling this internal prop thereafter.