From cd62d90de881b068311e0592ee0cb4abf923eb98 Mon Sep 17 00:00:00 2001 From: djmil Date: Fri, 10 Nov 2023 13:10:30 +0100 Subject: [PATCH] Polling hook useRef do not useState for internal values. which are not relevnat to rendering This will only trigger unnecessary rerenders --- webapp/src/api/games.js | 2 +- webapp/src/api/leaderboard.js | 2 +- webapp/src/api/user.js | 2 +- webapp/src/{util => hook}/Polling.js | 40 ++++++++++++++++------------ 4 files changed, 26 insertions(+), 20 deletions(-) rename webapp/src/{util => hook}/Polling.js (51%) diff --git a/webapp/src/api/games.js b/webapp/src/api/games.js index f0d2e25..01d4501 100644 --- a/webapp/src/api/games.js +++ b/webapp/src/api/games.js @@ -1,4 +1,4 @@ -import usePolling from '../util/Polling'; +import usePolling from '../hook/Polling'; export default function useGamesApi(dispatchGames) { diff --git a/webapp/src/api/leaderboard.js b/webapp/src/api/leaderboard.js index a653e35..c4901b8 100644 --- a/webapp/src/api/leaderboard.js +++ b/webapp/src/api/leaderboard.js @@ -1,5 +1,5 @@ import { useState } from "react"; -import usePolling from "../util/Polling"; +import usePolling from "../hook/Polling"; export default function useLeaderboardApi() { const [leaderboard, setLeaderboard] = useState(null); diff --git a/webapp/src/api/user.js b/webapp/src/api/user.js index 1b863a0..18f199c 100644 --- a/webapp/src/api/user.js +++ b/webapp/src/api/user.js @@ -1,4 +1,4 @@ -import usePolling from "../util/Polling"; +import usePolling from "../hook/Polling"; import useUserReducer from "../reducer/user"; export default function useUserApi() { diff --git a/webapp/src/util/Polling.js b/webapp/src/hook/Polling.js similarity index 51% rename from webapp/src/util/Polling.js rename to webapp/src/hook/Polling.js index 4446656..abfa3b7 100644 --- a/webapp/src/util/Polling.js +++ b/webapp/src/hook/Polling.js @@ -1,4 +1,4 @@ -import { useState, useCallback, useEffect, } from "react" +import { useState, useRef, useCallback, useEffect, } from "react" /* - uri: string @@ -9,13 +9,18 @@ import { useState, useCallback, useEffect, } from "react" */ export default function usePolling(uri, onResponce, mode = null) { - const [initialPoll, setInitialPoll] = useState(true); const [isPolling, setPolling] = useState(false); - const [intervalTimer, setIntervalTimer] = useState(null); + + const initialPollRef = useRef(true); + const initialPoll = initialPollRef.current; + + const intervalTimerIdRef = useRef(null); + const intervalTimerId = intervalTimerIdRef.current; + const pollData = useCallback(() => { setPolling(true); - setInitialPoll(false); + initialPollRef.current = false; fetch(uri) .then((responce) => { @@ -23,8 +28,7 @@ export default function usePolling(uri, onResponce, mode = null) { if (typeof mode?.interval_sec === 'number') { console.log("Schedule", uri, "fetch in", mode.interval_sec, "sec"); - const intervalTimer = setTimeout(pollData, mode.interval_sec * 1000); - setIntervalTimer(intervalTimer); + intervalTimerIdRef.current = setTimeout(pollData, mode.interval_sec * 1000); } return responce.json(); @@ -35,21 +39,23 @@ export default function usePolling(uri, onResponce, mode = null) { .catch((err) => { console.warn(err.message); }) - }, [uri, mode, onResponce]); + }, [uri, mode, onResponce, initialPollRef, intervalTimerIdRef]); + + const stopPollInterval = useCallback(() => { + console.log("Cancel scheduled fetch for", uri); + clearTimeout(intervalTimerId); + intervalTimerIdRef.current = null; + initialPollRef.current = true; + }, [uri, intervalTimerId, intervalTimerIdRef, initialPollRef]); useEffect(() => { - if ((initialPoll || (typeof mode?.interval_sec === 'number' && intervalTimer === null)) && !isPolling) { + if ((initialPoll || (typeof mode?.interval_sec === 'number' && intervalTimerId === null)) && !isPolling) { pollData(); + } else + if (mode?.interval_stop && intervalTimerId) { + stopPollInterval(); } - }, [initialPoll, mode, intervalTimer, isPolling, pollData]); - - if (mode?.interval_stop && intervalTimer) { - console.log("Cancel scheduled fetch for", uri); - clearTimeout(intervalTimer); - setIntervalTimer(null); - setInitialPoll(true); - } - + }, [initialPoll, mode, intervalTimerId, isPolling, pollData, stopPollInterval]); return isPolling; } \ No newline at end of file