React: make Poll into a hook

This commit is contained in:
djmil 2023-10-19 15:20:18 +02:00
parent 5821a02ba1
commit c884494618
7 changed files with 37 additions and 50 deletions

View File

@ -9,10 +9,7 @@ import {
import Header from "./components/Header" import Header from "./components/Header"
import Leaderboard from "./components/Leaderboard" import Leaderboard from "./components/Leaderboard"
import GameProposal from "./components/GameProposal" import GameProposal from "./components/GameProposal"
import DataPolling from './components/DataPolling'; import DataPolling from './components/OfflineToggle';
//import { UserProvider } from "../contexts/UserProvider"
//import { GameProposalProvider } from './context/GameProposal';
function App() { function App() {

View File

@ -1,16 +0,0 @@
import React from "react"
import { AppData } from "../../context/data"
import { AppContext } from "../../context/app"
export default function DataPolling() {
const [appData, dispatchData] = React.useContext(AppData)
//const [appCtx, dispatchAppData] = React.useContext(AppContext)
return <div className={DataPolling.name}>
polling
<button onClick={() => dispatchData({type: "togglePolling"})}>
{ appData.disablePolling === true ? "off" : "on" }
</button>
{ appData.fetching }
</div>
}

View File

@ -5,7 +5,7 @@ import Reject from './Reject'
import Cancel from './GameProposalCancel' import Cancel from './GameProposalCancel'
import { AppData } from "../../context/data" import { AppData } from "../../context/data"
//import { AppContext } from "../../context/app"
export default function GameProposal() { export default function GameProposal() {
const [data] = React.useContext(AppData) const [data] = React.useContext(AppData)

View File

@ -0,0 +1,12 @@
import React from "react"
import { AppData } from "../../context/data"
export default function OfflineToggle() {
const [appData, dispatchData] = React.useContext(AppData)
return <div className="OfflineToggle">
<button onClick={() => dispatchData({type: "toggleOfflineMode"})}>
{ appData.offlineMode === true ? "offline" : "online" }
</button>
</div>
}

View File

@ -9,8 +9,8 @@ import { useState, useCallback, useEffect, } from "react"
- stop - stop
*/ */
export default function Poll(url, interval_sec, disabled) { export default function Poll(url, interval_sec, offlineMode) {
const [cache, setCache] = useState(null) const [dataCache, setDataCache] = useState(null)
const [fetching, setFetching] = useState(false) const [fetching, setFetching] = useState(false)
const [timeoutID, setTimeoutID] = useState(null) const [timeoutID, setTimeoutID] = useState(null)
@ -23,27 +23,24 @@ export default function Poll(url, interval_sec, disabled) {
setFetching(false) setFetching(false)
return response.json() return response.json()
}) })
.then((freshData) => setCache(freshData)) .then((freshData) => setDataCache(freshData))
.catch((err) => console.log(err.message)) .catch((err) => console.log(err.message))
}, [url]) }, [url])
useEffect(() => { useEffect(() => {
if (cache == null) { if (dataCache == null) {
fecthData() // <<-- run immediatly on startup fecthData() // <<-- run immediatly on startup
} }
else if (disabled === true) { else if (offlineMode === true) {
clearTimeout(timeoutID) // cancel already scheduled fetch clearTimeout(timeoutID) // cancel already scheduled fetch
setTimeoutID(null) setTimeoutID(null) // & stop interval fetching
} }
else if (timeoutID === null) { else if (timeoutID === null) {
const timeoutID = setTimeout(fecthData, interval_sec * 1000) const timeoutID = setTimeout(fecthData, interval_sec * 1000)
setTimeoutID(timeoutID) setTimeoutID(timeoutID)
console.log("Fetch '" +url +"' scheduled in " +interval_sec +" sec") console.log("Fetch '" +url +"' scheduled in " +interval_sec +" sec")
} }
}, [url, cache, fecthData, timeoutID, disabled, interval_sec]); }, [url, dataCache, fecthData, timeoutID, offlineMode, interval_sec]);
return { return [ dataCache, fetching ]
data: cache,
fetching
}
} }

View File

@ -12,19 +12,14 @@ export const AppDataProvider = ({ children }) => {
const [data, dispatchData] = React.useReducer(reducer, initialState) const [data, dispatchData] = React.useReducer(reducer, initialState)
const games = Poll('api/gamestate', 30, data.disablePolling) const [games, gamesFetching ] = Poll('api/gamestate' , 30, data.offlineMode)
const leaderboard = Poll('api/leaderboard', 60, data.disablePolling) const [leaderboard, leaderboardFetching ] = Poll('api/leaderboard', 60, data.offlineMode)
data.games = games.data data.games = games
data.leaderboard = leaderboard.data data.gamesFetching = gamesFetching
var fetching = [] data.leaderboard = leaderboard
if (games.fetching === true) data.leaderboardFetching = leaderboardFetching
fetching = [...fetching, "games"]
if (leaderboard.fetching === true)
fetching = [...fetching, "leaderboard"]
data.fetching = fetching
return ( return (
<AppData.Provider value={[data, dispatchData]}> <AppData.Provider value={[data, dispatchData]}>

View File

@ -1,9 +1,9 @@
export const reducer = (state, action) => { export const reducer = (state, action) => {
switch (action.type) { switch (action.type) {
case "togglePolling": case "toggleOfflineMode":
return { ...state, return { ...state,
disablePolling: !state.disablePolling // on/off offlineMode: !state.offlineMode // on/off
} }
default: default:
@ -14,8 +14,10 @@ export const reducer = (state, action) => {
export const initialState = { export const initialState = {
games: null, games: null,
leaderboard: null, gamesFetching: false,
disablePolling: false, leaderboard: null,
fetching: [] leaderboardFetching: false,
offlineMode: false
} }