'How to call a function every minute in a React component?

I make a table to get stock price quotes, it works well, but when I try to put a function include setState in the component, it falls into an infinite loop, it triggers setState and re-render immediately and triggers again.

How can I call this function without triggering an infinite loop when I load this component? I would to call the function every 10 seconds or every minute.

import React, { useState } from 'react'
import api from '../../api'

function CreateRow(props){
    
    const [stock, setStock] = useState({symbol:'',last:'',change:''})
    

    async function check() {
        const result = await api.getStock(props.item)
        console.log(props.item)
        const symbol = result.data.symbol
        const lastest = result.data.latestPrice
        const change = result.data.change
        setStock({symbol:symbol, lastest:lastest, change:change})
    }


    // check()   <----------! if I call the function here, it becomes an infinite loop.


    return(
        <tr>
            <th scope="row"></th>
            <td>{stock.symbol}</td>
            <td>{stock.lastest}</td>
            <td>{stock.change}</td>
        </tr>
    )
}

export default CreateRow


Solution 1:[1]

You want to initiate a timeout function inside a lifecycle method.

Lifecycle methods are methods which call on, for example, mount and unmount (there are more examples but for the sake of explanation I will stop here)

what you're interested in is the mount lifecycle.

In functional components, it can be accessed like this:

const { useEffect } from 'react';

useEffect(() => {
  // This will fire only on mount.
}, [])

In that function, you want to initialize a setTimeout function.

const MINUTE_MS = 60000;

useEffect(() => {
  const interval = setInterval(() => {
    console.log('Logs every minute');
  }, MINUTE_MS);

  return () => clearInterval(interval); // This represents the unmount function, in which you need to clear your interval to prevent memory leaks.
}, [])

Solution 2:[2]

Consider 60000 milliseconds = 1 minute

Can do using the method:

setInterval(FunctionName, 60000)

do as below:

async function check() {
  const result = await api.getStock(props.item)
  console.log(props.item)
  const symbol = result.data.symbol
  const lastest = result.data.latestPrice
  const change = result.data.change
  setStock({symbol:symbol, lastest:lastest, change:change})
}

// Write this line

useEffect(() => {
  check()
 }, []);


setInterval(check, 60000);

Solution 3:[3]

you also do that with setTimeout

import React, { useState, useEffect } from "react";

export const Count = () => {
const [counts, setcounts] = useState(0);

async function check() {
  setcounts(counts + 1);
}

// Write this line
useEffect(() => {
check();
}, []);

 console.log("hello dk - ",counts)

 setTimeout(() => {
    check();
   }, 1000);

return <div>Count : - {counts}</div>;

};

Solution 4:[4]

import React, { useState, useEffect } from "react";

export const Count = () => {
const [currentCount, setCount] = useState(1);

useEffect(() => {
 if (currentCount <= 0) {
   return;
 }

 const id = setInterval(timer, 1000);
 return () => clearInterval(id);
}, [currentCount]);

const timer = () => setCount(currentCount + 1);

console.log(currentCount);

return <div>Count : - {currentCount}</div>;
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Alan W. Smith
Solution 3 Deepak Singh
Solution 4 Deepak Singh