Search code examples
reactjsreact-hookssetinterval

React - useEffect with setInterval


I have a Functional Component with setInterval inside useEffect. But value inside loadData is always equal to initial one (0), despite the correct render.

How I can get the current value inside loadData that calling by setInterval?

    ...
    const [value, setValue] = useState(0);
    const [service, setService] = useState();

    useEffect(() => {
        setService(new ApiService());
    }, [])

    useEffect(
        () => {
            const timerId = setInterval(loadData, 1000 * 5);
            return () => clearInterval(timerId);
        }, 
        [service]
    )

    async function loadData() {
        const result = await service.getData();
        console.log("old value: ", value); // "value" is always 0 (initial)
        setValue(result.data.value);
    } 

    ...

Solution

  • Your code depends on the value constant to update it. Intuitively this makes sense, but the problem has to do with closures. setValue and value are defined during the render cycle of the component. In other words, their definition is fixed.

    The set function (setValue) of useState() passes the current/old value as a parameter. You should use this functional updates approach in useState():

    setValue((prevState) => {
      console.log("old value: ", prevState);
      return result.data.value;
    });