Timer w React Component

Wywoływanie rekurencyjne funkcji w React-cie z wykorzystaniem „setTimeout” i odwoływanie się w nich do stanów jest dość problematyczne. Taka funkcja „widzi zamrożony stan” pomimo tego, że może go zmieniać.

Poniżej sposób na timer (wykonywanie akcji z opóźnieniem) z możliwością dostępu do stanów w komponencie Reacta.

const [timerCounter, setTimerCounter] = useState(0);

useEffect(() => {
    const id = setTimeout(
        () => setTimerCounter(timerCounter + 1),
        1000
    );
    console.log("TIK", timerCounter);
    return () => clearTimeout(id);
}, [timerCounter]);

Przykład heartbeat-a odpytującego API

const [doReloadTime, setDoReloadTime] = useState(1000);
const [fetchState, setFetchState] = 
    useState<string>("waiting");

// aktualizacja danych
const onData = useCallback((data: any) => {
    // ...
}, []);

// pobieranie danych z API
const reloadData = useCallback(() => {

    setFetchState("waiting");

    fetch(...)
        .then(res => {
            onData(res);
            setFetchState("done");
            setDoReloadTime(1000);

        })
        .catch(err => {
            onData(null);
            setFetchState("error");
            setDoReloadTime(5000);
        });
}, [onData]);

// heartbeat
useEffect(() => {
    if (!reloadData || doReloadTime <= 0)
        return;

    setTimeout(() => {
        reloadData();
    }, doReloadTime);

    setDoReloadTime(0);
}, [doReloadTime, reloadData]);