Polling hook useRef

do not useState for internal values. which are not relevnat to rendering
This will only trigger unnecessary rerenders
This commit is contained in:
djmil 2023-11-10 13:10:30 +01:00
parent 453a45d980
commit cd62d90de8
4 changed files with 26 additions and 20 deletions

View File

@ -1,4 +1,4 @@
import usePolling from '../util/Polling'; import usePolling from '../hook/Polling';
export default function useGamesApi(dispatchGames) { export default function useGamesApi(dispatchGames) {

View File

@ -1,5 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import usePolling from "../util/Polling"; import usePolling from "../hook/Polling";
export default function useLeaderboardApi() { export default function useLeaderboardApi() {
const [leaderboard, setLeaderboard] = useState(null); const [leaderboard, setLeaderboard] = useState(null);

View File

@ -1,4 +1,4 @@
import usePolling from "../util/Polling"; import usePolling from "../hook/Polling";
import useUserReducer from "../reducer/user"; import useUserReducer from "../reducer/user";
export default function useUserApi() { export default function useUserApi() {

View File

@ -1,4 +1,4 @@
import { useState, useCallback, useEffect, } from "react" import { useState, useRef, useCallback, useEffect, } from "react"
/* /*
- uri: string - uri: string
@ -9,13 +9,18 @@ import { useState, useCallback, useEffect, } from "react"
*/ */
export default function usePolling(uri, onResponce, mode = null) { export default function usePolling(uri, onResponce, mode = null) {
const [initialPoll, setInitialPoll] = useState(true);
const [isPolling, setPolling] = useState(false); 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(() => { const pollData = useCallback(() => {
setPolling(true); setPolling(true);
setInitialPoll(false); initialPollRef.current = false;
fetch(uri) fetch(uri)
.then((responce) => { .then((responce) => {
@ -23,8 +28,7 @@ export default function usePolling(uri, onResponce, mode = null) {
if (typeof mode?.interval_sec === 'number') { if (typeof mode?.interval_sec === 'number') {
console.log("Schedule", uri, "fetch in", mode.interval_sec, "sec"); console.log("Schedule", uri, "fetch in", mode.interval_sec, "sec");
const intervalTimer = setTimeout(pollData, mode.interval_sec * 1000); intervalTimerIdRef.current = setTimeout(pollData, mode.interval_sec * 1000);
setIntervalTimer(intervalTimer);
} }
return responce.json(); return responce.json();
@ -35,21 +39,23 @@ export default function usePolling(uri, onResponce, mode = null) {
.catch((err) => { .catch((err) => {
console.warn(err.message); 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(() => { useEffect(() => {
if ((initialPoll || (typeof mode?.interval_sec === 'number' && intervalTimer === null)) && !isPolling) { if ((initialPoll || (typeof mode?.interval_sec === 'number' && intervalTimerId === null)) && !isPolling) {
pollData(); pollData();
} else
if (mode?.interval_stop && intervalTimerId) {
stopPollInterval();
} }
}, [initialPoll, mode, intervalTimer, isPolling, pollData]); }, [initialPoll, mode, intervalTimerId, isPolling, pollData, stopPollInterval]);
if (mode?.interval_stop && intervalTimer) {
console.log("Cancel scheduled fetch for", uri);
clearTimeout(intervalTimer);
setIntervalTimer(null);
setInitialPoll(true);
}
return isPolling; return isPolling;
} }