when route changes in my React app I clearInterval() and app breaks
Asked Answered
A

2

3

I'm working on a React app with React-router-dom.

I have a menu with some react-router-dom's <NavLink />, each one takes me to a different route.

In my main route path="/" I have chartComponent with a chart that keeps on changing with random data, like this: this.chartChangeId = setInterval(()=> this.setState(data), 1500).

before I added this:

componentWillUnmount(){
    clearInterval(this.chartChangeId);
}

To chartComponent my app didn't break, but I got this error:

Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op. Please check the code for the BrainWaveChart component.

so I added this to the life cycle.

But now, when I click on one of the <NavLink /> to go to a different route my app breaks, and I get this error:

Uncaught TypeError: timeout.close is not a function at exports.clearTimeout.exports.clearInterval (main.js:14) at BrainWaveChart.componentWillUnmount (brainwaveChart.jsx:116) at callComponentWillUnmountWithTimer (vendor_f02cab182c1842c98837.js:45235) at HTMLUnknownElement.callCallback (vendor_f02cab182c1842c98837.js:37015) at Object.invokeGuardedCallbackDev (vendor_f02cab182c1842c98837.js:37054) at invokeGuardedCallback (vendor_f02cab182c1842c98837.js:36911) at safelyCallComponentWillUnmount (vendor_f02cab182c1842c98837.js:45242) at commitUnmount (vendor_f02cab182c1842c98837.js:45368) at commitNestedUnmounts (vendor_f02cab182c1842c98837.js:45404) at unmountHostComponents (vendor_f02cab182c1842c98837.js:45687)

Am I doing it wrong ?

Anglophobe answered 21/12, 2017 at 11:9 Comment(0)
L
7

()=> this.setState(data) is executing even if you clear interval because its already in memory and its in async stack. What you need to do is check if the component exists and only then update state. The simplest thing what to do is

const {clearInterval, setInterval} = window;
class Comp extends React.Component {
  constructor(props) {
    super(props);
    this.mounted = false;
    this.interval = setInterval(() => {
      if(this.mounted) this.setState();
    })
  }
  componentWillMount() {
    this.mounted = true;
  }
  componentWillUnmount() {
    this.mounted = false;
    clearInterval(this.interval);
  }
}

However this is more of antipatern. Proper way would be not to use setState in Ajax at all. https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html

Lucinalucinda answered 21/12, 2017 at 12:20 Comment(0)
S
0

Your IDE probably imported { clearInterval } automatically for you,
and that's what causing the problem.
Please check if you have import { clearInterval } from .... statement in your file,
and remove it.
It happens in some IDE's.
More info available in this link:
https://github.com/angular/angular/issues/12400

Seize answered 21/12, 2017 at 12:21 Comment(1)
@AjayGupta, if you have read the thread in the link that I shared you would understand that this is an IDE specific issue and not a framework issue.Seize

© 2022 - 2024 — McMap. All rights reserved.