Home > Enterprise >  Update object every second with useState hook
Update object every second with useState hook

Time:04-20

I am generating a random number every 2 seconds and checking if my state object, data, has this number as a key. If so, then increment the value otherwise insert it into the object as a new field with a default value of 1. However, whenever the random number function runs, my state object, data, is empty so data.hasOwnProperty is always false. Why is this the case?

  const [data, setData] = useState({});
  useEffect(() => {
    //INTERVAL TO GENERATE RANDOM NUMBER EVERY 2 SECONDS
    const interval = setInterval(() => {
      generateRandomStock();
    }, 2000);

    return () => {
      clearInterval(interval);
    };
  }, []);

  //GENERATES A RANDOM NUMBER AND UPDATES THE STATE 
  const generateRandomStock = () => {
    const randNumber = Math.floor(Math.random() * 9   1).toString();
    console.log(data)
    if (data.hasOwnProperty(randNumber)) {
      console.log("has");
      setData((prevState) => ({
        ...prevState,
        [randNumber]: prevState[randNumber]   1,
      }));
    } else {
      console.log("does not have");
      setData((prevState) => ({
        ...prevState,
        [randNumber]: 1,
      }));
    }
  };

CodePudding user response:

The generateRandomStock function creates a closure with initial data value. That's always an empty object {}. You can access the data received to the callback function to `setData method where it gives updated values.

Try like below

  const generateRandomStock = () => {
    const randNumber = Math.floor(Math.random() * 9   1).toString();
    setData((prevData) => {
      console.log(prevData);
      if (prevData.hasOwnProperty(randNumber)) {
        return {
          ...prevData,
          [randNumber]: prevData[randNumber]   1
        };
      } else {
        console.log("does not have");

        return {
          ...prevData,
          [randNumber]: 1
        };
      }
    });
  };

Edit wizardly-brattain-ycquuj

CodePudding user response:

You need to add generateRandomStock function as a dependency in useEffect hook. Since this function uses the data value, its content is updated when the data value is updated.

const [data, setData] = useState({});

  //GENERATES A RANDOM NUMBER AND UPDATES THE STATE
  const generateRandomStock = () => {
    const randNumber = Math.floor(Math.random() * 9   1).toString();
    console.log(data);
    if (data.hasOwnProperty(randNumber)) {
      console.log("has");
      setData((prevState) => ({
        ...prevState,
        [randNumber]: prevState[randNumber]   1
      }));
    } else {
      console.log("does not have");
      setData((prevState) => ({
        ...prevState,
        [randNumber]: 1
      }));
    }
  };

  useEffect(() => {
    //INTERVAL TO GENERATE RANDOM NUMBER EVERY 2 SECONDS
    const interval = setInterval(() => {
      generateRandomStock();
    }, 2000);

    return () => {
      clearInterval(interval);
    };
  }, [generateRandomStock]);
  • Related