Search code examples
reactjsintervals

Why is this setInterval cause value over 1?


I have a progress bar the value should be from 0.1 to 1.

but sometimes progressValue will over 1, for example refresh the page.

Why ?

https://codesandbox.io/p/devbox/g9wwqf?file=%2Fsrc%2FApp.jsx%3A6%2C1

import "./styles.css";
import axios from "axios";
import { useState, useEffect } from "react";

let intervalId;

export default function App() {
  const [progressValue, setProgressValue] = useState(0);

  useEffect(() => {
    intervalId = setInterval(() => {
      if (progressValue < 1) {
        setProgressValue((t) => t + 0.3);
      }
    }, 100);

    return () => clearInterval(intervalId);
  }, []);

  useEffect(() => {
    axios
      .get("https://randomuser.me/api/?results=5")
      .then((value) => {
        // success
        clearInterval(intervalId);
        setProgressValue(1);
      })
      .catch((error) => {
        // error
        clearInterval(intervalId);
        setProgressValue(1);
      });
  }, []);

  console.log("progressValue =>", progressValue);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

Solution

  • Please pass the progressValue dependency correctly to the effect. Otherwise the progressValue will always refer to the value of progressValue from the very first render, which was 0.

    If you log the value of progressValue before the if condition, it will log 0. That's just how closures work. So anyway doing that condition check will do you no good.

    enter image description here

    Instead you can make use of the condition inside the setState callback correctly like:

      useEffect(() => {
        intervalId = setInterval(() => {
          setProgressValue((t) => {
            if (t + 0.3 <= 1) return t + 0.3;
            else return t;
          });
        }, 100);
    
        return () => clearInterval(intervalId);
      }, []);
    
    

    I am sure you are looking for the sum value to not exceed 1, so the conditions should check for that and not t < 1