Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cant append array(state element) with setinterval() in react

 const [timer,setTimer] = useState()
 const [number, setNumber] = useState()
 const [list, setlist] = useState([])

const numberChange = (number)=>{
    setNumber(number)
    if (!(list.find(item=>item===number))){
        setlist([...list,number])}
  }

  const randomNumber=()=> 1+Math.floor(Math.random()*90)

  const randNumberChange=()=>{
    let randNumber = randomNumber()
    if (list.find(item=>item===randNumber))
      randNumberChange()
      else
    numberChange(randNumber)
  }

  const startTimer = () => {
   setTimer(setInterval(()=>{
        randNumberChange()
   }, 5000))
}

const stopTimer=()=>{
    clearInterval(timer)
}

The list is always rendering only one item and not appending it.

When randNumberChange is called separately then the list gets appended but not with setInterval.

When startTimer funcion is executed is stopped with stopTimer and then started again it appends second item then stop and it repeats

like image 722
Himanshu Jain Avatar asked Jan 31 '26 17:01

Himanshu Jain


1 Answers

Change setlist([...list,number])} to setlist((prevState) => [...prevState, number]). React set state is async in nature. So to get the correct list value from the state you would need to get the value from previous state. Doc

Suggestion: that instead of setting timer in state, you can start the interval in useEffect.

Also in numberChange function, you should get the list from previous state and then append the new number in that. This will make sure that the list value is updated before adding new number.

import React, { Component, useState } from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import "./style.css";
const Test = () => {
  const [number, setNumber] = useState(null);
  const [list, setlist] = useState([]); 

  const numberChange = number => {
    setNumber(number);
    if (!list.find(item => item === number)) {
      setlist((prevState) => [...prevState, number]);// instead of directly using list value, get it from previous state
    }
  };

  const randomNumber = () => 1 + Math.floor(Math.random() * 90);

  const randNumberChange = () => {
    console.log("here");
    let randNumber = randomNumber();
    if (list.find(item => item === randNumber)) randNumberChange();
    else numberChange(randNumber);
  };

  const startTimer = () => {
     return setInterval(() => { randNumberChange(); }, 5000);
  }

  const stopTimer = (timer) => {
     clearInterval(timer)
  }

  React.useEffect(() => {
    const timer = startTimer();
    return ()=> stopTimer(timer);
  }, []);

  console.log(list);
  return <div>{number}</div>;
};
like image 193
Jagrati Avatar answered Feb 02 '26 10:02

Jagrati