Abdul Wahab
Abdul Wahab

Reputation: 191

clearInterval is not working in reactjs

SetInterval is working fine, but clearInterval is not working

See my code, i have parent class Channel and and Child class Body, within body when componentDidMount is called, then i setInterval for function refreshState. In refreshState function i try to clearInterval which is not working

var Header = require('../../common/header.jsx');
var Sidebar = require('../../common/sidebar.jsx');
var Footer = require('../../common/footer.jsx');

var Body = React.createClass({

  componentDidMount: function() {
    this.intervalId  = setInterval(this.refreshStats, 1000);
  },

  componentWillUnmount: function(){
    clearInterval(this.intervalId);
  },

  refreshStats: function() {
        console.log(this.intervalId);
        clearInterval(this.intervalId);
  },

  render: function() {
    return (
      <Container id='body'>
        <Grid>
          <Row>
            <Col sm={12}>
              <PanelContainer>
                <Panel>
                  <PanelBody>
                    Test
                  </PanelBody>
                </Panel>
              </PanelContainer>
            </Col>
          </Row>
        </Grid>
      </Container>
    );
  }
});

var Channel = React.createClass({
  mixins: [SidebarMixin, State],
  render: function() {
    var classes = React.addons.classSet({
      'container-open': this.state.open
    });
    return (
      <Container id='container' className={classes}>
        <Sidebar />
        <Header />
        <Body />
        <Footer />
      </Container>
    );
  }
});

module.exports = Channel;

Upvotes: 17

Views: 39167

Answers (6)

SummmerFort
SummmerFort

Reputation: 451

You can refer to this example: https://beta.reactjs.org/reference/react/useRef#referencing-a-value-with-a-ref

Since you do not want to trigger a re-render for your state change, it is better to use a ref.

In a class component you can use this in your constructor

this.intervalRef = React.createRef();

For a functional component:

const intervalRef = useRef();

Upvotes: 0

vishal Devmurari
vishal Devmurari

Reputation: 3

I think you need to pass interval id. If you log this.intervalId it will object.

So your code should be like: clearInterval(this.intervalId._id);

Upvotes: 0

Majid Savalanpour
Majid Savalanpour

Reputation: 1823

Sometimes you need to run a command in an interval using window.setInterval.

When you navigate away from the component (to simulate unmounting), the interval still runs.

Even worse, when you navigate back to Greeting component, another interval process starts!

How to Fix the Issue You need to save the interval ID when you call the setInterval

class Example extends Component {
  intervalID = 0;

  componentDidMount() {
    this.intervalID = setInterval(this.hello, 1000);
  }
  ...
}

To cancel setInterval, you need to call clearInterval, which require the interval ID returned when you called setInterval.

The best place to do is right before the component unmounts (componentWillUnmount).

class Example extends Component {
  intervalID = 0;

  componentDidMount() {
    this.intervalID = setInterval(this.hello, 1000);
  }

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

Upvotes: 6

Fralle
Fralle

Reputation: 937

I got it working by using clearInterval on the internal Id from the object returned.

componentDidMount() {
  this.interval = setInterval(this.timer, 1000)
  console.log(this.interval) // Timeout {_id: 5, _clearFn: ƒ}
}

componentWillUnmount() {
  clearInterval(this.interval._id)
}

Upvotes: 3

Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27306

Another way is to save it directly on this:

var Body = React.createClass({

componentDidMount: function() {
    this.intervalId  = setInterval(this.refreshStats, 1000);
},

componentWillUnmount: function(){
   clearInterval(this.intervalId);
},

refreshStats: function() {
    console.log(this.intervalId);
    clearInterval(this.intervalId);
},

render: function() {
    ...
}
});

This requires fewer lines of code but it feels a little less clean. I myself save it on state as the accepted answer suggests, but I am posting this in case someone more knowledgeable might comment on which method is more idiomatic.

Note also that by using the React Timer mixin you don't have to worry about unmount cleanup - this applies to whether you save the intervalId in state or on this.

Upvotes: 20

Davin Tryon
Davin Tryon

Reputation: 67336

In order to keep a handle on the intervalId, you would need to save it in state:

var Body = React.createClass({

  getInitialState = function() {
    return {};
  },

  componentDidMount: function() {
    intervalId  = setInterval(this.refreshStats, 1000);
    this.setState({intervalId: intervalId});
  },

  componentWillUnmount: function(){
    clearInterval(this.state.intervalId);
  },

  refreshStats: function() {
    console.log(this.state.intervalId);
    clearInterval(this.state.intervalId);
  },

  render: function() {
    ...
  }
});

Otherwise, it won't survive the render cycle.

Upvotes: 17

Related Questions