Source:  Twitter logo

I am trying to change the state of a component every 5 seconds as below inside componentDidMount() hook

import React, { Component } from 'react';

export default class ToTest extends Component {

  constructor(props) {
    super(props);
    this.state = {
      test: false
    };
  }

  componentDidMount() {
    setTimeout(() => { this.setState({ test: !this.state.test }) }, 5000);
  }

  renderDiv() {
    if(this.state.test) {
      return (<div>test is true</div>)
    }
    else {
      return (<div>test is false</div>)
    }
  }
  render() {
    return (
      <div>{ this.renderDiv() }</div>
    );
  }
}

But it executes only once. It changes from false to true once and then nothing. What am I missing?

componentDidMount() is only executed once when the component mounts and you only schedule it once. You have to use setInterval() to schedule it periodically.

Also when you update the state based on the current state you should use a callback in setState() that takes the previous state as react may batch multiple calls to setState().

And don't forget to cancel the timer in componentWillUnmount():

import React, { Component } from 'react';

export default class ToTest extends Component {
    state = {
        test: false,
    };

    componentDidMount() {
        this.timer = setInterval(
            () => this.setState(prevState => ({ test: !prevState.test })),
            5000,
        );
    }

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

    // other methods ...
}
13 users liked answer #0dislike answer #013
trixn profile pic
trixn

Well setTimeout will only execute once, what you are looking for is setInterval:

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout

The setTimeout() method of the WindowOrWorkerGlobalScope mixin (and successor to window.setTimeout) sets a timer which executes a function or specified piece of code once after the timer expires.

Compare with

The setInterval() method of the WindowOrWorkerGlobalScope mixin repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.

4 users liked answer #1dislike answer #14
Martin Schneider profile pic
Martin Schneider

As said in comments, you must use setInterval. the function setTimeout is called once. Make sure to clear the setInterval when the component unmounts. https://reactjs.org/docs/react-component.html#componentwillunmount

The code.

import React, { Component } from 'react';

export default class ToTest extends Component {

  constructor(props) {
    super(props);
    this.state = {
      test: false
    };
  }

  componentDidMount() {
    this.timer = setInterval(() => { this.setState({ test: !this.state.test }) }, 5000);
  }

  componentWillUnmount() {
    clearInterval(this.timer)
  }


  renderDiv() {
    if(this.state.test) {
      return (<div>test is true</div>)
    }
    else {
      return (<div>test is false</div>)
    }
  }
  render() {
    return (
      <div>{ this.renderDiv() }</div>
    );
  }
}
2 users liked answer #2dislike answer #22
Damien profile pic
Damien

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).