Amrit Anand
Amrit Anand

Reputation: 17

setState getting updated multiple times

I am incrementing a counter by setState() of React using a setInterval method. But for every intervals the application is updating multiple times.

import React, { Component } from 'react';

export default class Arrival extends Component {
state = {
    count: 0,
    limitTo: 6
  }
  render() {
    try {
      setInterval(() => {
        this.setState({
          limitTo: this.state.limitTo + 6
        })
        console.log(this.state)
      }, 5000);
    } catch(err) {
      console.log(err)
    }
  return()
}
}

In the first 5 seconds, the state is getting updated once.

In the next 5 seconds, the state is getting updated 2 times.

In the next 5 seconds, the state is getting updated 4 times. and so on...

I want the state to only get updated once every 5 seconds.

Upvotes: 0

Views: 210

Answers (2)

cegas
cegas

Reputation: 3091

setInterval() is called in render() method. This means that:

  1. It will be set off the first time it is rendered. Timers ticking: 1.
  2. After 5 seconds, it will fire and change the state. It means the component will need to rerender.
  3. Rendering starts another timer, since setInterval() is called in render() method. Timers ticking: 2.
  4. Another 5 seconds pass. First timer ticks again, which causes component to rerender due to state change. Another timer is set off. Timers ticking: 3.
  5. Second timer ticks for the first time. Another rerender happens and causes a 4th timer to be started. Timers ticking: 4.
  6. Ad infinitum

To solve this, move setInterval to componentDidMount() as recommended by another answer to ensure the timer is started once only, not on each render.

Upvotes: 1

Jee Mok
Jee Mok

Reputation: 6556

when the state update, the component will be also updated and re-render, hence the setInterval should not be inside render method. You can do this instead:

class Arrival extends Component {
  state = {
    count: 0,
    limitTo: 6
  };

  interval = 0;

  componentDidMount() {
    try {
      this.interval = setInterval(() => {
        this.setState({
          limitTo: this.state.limitTo + 6
        });
        console.log(this.state);
      }, 5000);
    } catch (err) {
      console.log(err);
    }
  }

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

  render() {
    return <div />;
  }
}

Edit busy-flower-wj0x5

Note: reminded by @FrankerZ, you should also clean up the interval when the component unmounts, otherwise the clock will keep ticking ;)

Upvotes: 1

Related Questions