useXxxReducer
This commit is contained in:
parent
9ec2059c4a
commit
b58c71c876
@ -1,31 +1,34 @@
|
|||||||
import './App.css';
|
import './App.css';
|
||||||
import React, { useReducer } from 'react'
|
import React from 'react';
|
||||||
import { BrowserRouter, Routes, Route } from "react-router-dom"
|
import { BrowserRouter, Routes, Route } from "react-router-dom";
|
||||||
|
|
||||||
import Header from "./container/Header"
|
import Header from "./container/Header"
|
||||||
import Leaderboard from "./container/Leaderboard"
|
import Leaderboard from "./container/Leaderboard"
|
||||||
import Game from "./components/Game"
|
import Game from "./components/Game"
|
||||||
import About from "./components/About"
|
import About from "./components/About"
|
||||||
|
|
||||||
import Polling from './flux/polling';
|
import usePollingReducer from './reducer/polling';
|
||||||
import User from './flux/user';
|
import useUserReducer from './reducer/user';
|
||||||
|
import useLeaderboardReducer from './reducer/leaderboard';
|
||||||
|
|
||||||
import useLeaderboardApi from './api/leaderboard';
|
import useLeaderboardApi from './api/leaderboard';
|
||||||
import useUserApi from './api/user';
|
import useUserApi from './api/user';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const pollingFlux = useReducer(Polling.reducer, Polling.initialState);
|
const pollingReducer = usePollingReducer();
|
||||||
const userFlux = useReducer(User.reducer, User.initialState);
|
const userReducer = useUserReducer();
|
||||||
|
const leaderboardReducer = useLeaderboardReducer();
|
||||||
|
|
||||||
const leaderboardApi = useLeaderboardApi(pollingFlux);
|
const leaderboardApi = useLeaderboardApi(leaderboardReducer);
|
||||||
const userApi = useUserApi(userFlux);
|
const userApi = useUserApi(userReducer);
|
||||||
|
|
||||||
const leaderboard = leaderboardApi.get();
|
const leaderboard = leaderboardApi.get(pollingReducer);
|
||||||
const user = userApi.get();
|
const user = userApi.get();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App" >
|
<div className="App" >
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Header pollingFlux={pollingFlux} />
|
<Header pollingReducer={pollingReducer} />
|
||||||
<Routes>
|
<Routes>
|
||||||
{/* https://stackoverflow.com/questions/40541994/multiple-path-names-for-a-same-component-in-react-router */}
|
{/* https://stackoverflow.com/questions/40541994/multiple-path-names-for-a-same-component-in-react-router */}
|
||||||
<Route path="/game" element={<Game />} />
|
<Route path="/game" element={<Game />} />
|
||||||
|
@ -2,19 +2,26 @@ import usePolling from "../util/Polling"
|
|||||||
|
|
||||||
const uri = '/api/leaderboard';
|
const uri = '/api/leaderboard';
|
||||||
|
|
||||||
export default function useLeaderboardApi([polling, dispatchPolling]) {
|
export default function useLeaderboardApi(leaderboardReducer) {
|
||||||
|
const [leaderboard, dispatchLeaderboaed] = leaderboardReducer;
|
||||||
|
|
||||||
|
const useGet = (pollingReducer) => {
|
||||||
|
const [polling, dispatchPolling] = pollingReducer;
|
||||||
|
|
||||||
const useGet = () => {
|
|
||||||
const mode = (polling.enabled === true)
|
const mode = (polling.enabled === true)
|
||||||
? { interval_sec: 300 } // update leaderbord stats every 5 min
|
? { interval_sec: 300 } // update leaderbord stats every 5 min
|
||||||
: { interval_stop: true } // user has fliped OfflineToggel
|
: { interval_stop: true } // user has fliped OfflineToggel
|
||||||
|
|
||||||
const [leaderboard, isFetching] = usePolling(uri, mode);
|
const [table, isFetching] = usePolling(uri, mode);
|
||||||
|
|
||||||
if (polling.leaderboard !== isFetching) {
|
if (polling.leaderboard !== isFetching) {
|
||||||
dispatchPolling({ type: 'next', leaderboard: isFetching });
|
dispatchPolling({ type: 'next', leaderboard: isFetching });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (leaderboard.table !== table) {
|
||||||
|
dispatchLeaderboaed({ type: 'next', table });
|
||||||
|
}
|
||||||
|
|
||||||
return leaderboard;
|
return leaderboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@ import { NavLink } from "react-router-dom";
|
|||||||
import OnlineToggle from '../components/OnlineToggle';
|
import OnlineToggle from '../components/OnlineToggle';
|
||||||
import Wobler from '../components/Wobler';
|
import Wobler from '../components/Wobler';
|
||||||
|
|
||||||
export default function Header({ pollingFlux }) {
|
export default function Header({ pollingReducer }) {
|
||||||
const [polling, dispatchPolling] = pollingFlux;
|
const [polling, dispatchPolling] = pollingReducer;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='Header'>
|
<div className='Header'>
|
||||||
@ -33,4 +33,4 @@ export default function Header({ pollingFlux }) {
|
|||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -4,14 +4,15 @@ import Loading from '../components/Loading';
|
|||||||
|
|
||||||
export default function Leaderboard({ leaderboard, user }) {
|
export default function Leaderboard({ leaderboard, user }) {
|
||||||
|
|
||||||
if (leaderboard == null)
|
const table = leaderboard?.table;
|
||||||
|
if (!table)
|
||||||
return <Loading />
|
return <Loading />
|
||||||
|
|
||||||
const isCurrentUser = (playerName) =>
|
const isCurrentUser = (playerName) =>
|
||||||
user.isCurrentUser(playerName) === true ? true : null;
|
user?.isCurrentUser(playerName) === true ? true : null;
|
||||||
|
|
||||||
const tableRows = Object.keys(leaderboard).map(playerName => {
|
const tableRows = Object.keys(table).map(playerName => {
|
||||||
var rank = leaderboard[playerName];
|
var rank = table[playerName];
|
||||||
|
|
||||||
return <tr key={playerName} className={isCurrentUser(playerName) && 'currentuser'}>
|
return <tr key={playerName} className={isCurrentUser(playerName) && 'currentuser'}>
|
||||||
<td>{playerName}</td>
|
<td>{playerName}</td>
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
import { localeCompare } from '../util/Locale'
|
|
||||||
import StateHelper from '../util/StateHelper';
|
|
||||||
|
|
||||||
export const userInitialState = {
|
|
||||||
username: '',
|
|
||||||
isCurrentUser: function (otherUsername) {
|
|
||||||
return localeCompare(this.username, otherUsername)
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
export function userReducer(state, action) {
|
|
||||||
switch (action.type) {
|
|
||||||
|
|
||||||
case 'next':
|
|
||||||
return StateHelper.next(state, action);
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw Error('Unknown action.type: ' + action.type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const User = {
|
|
||||||
reducer: userReducer,
|
|
||||||
initialState: userInitialState
|
|
||||||
};
|
|
||||||
|
|
||||||
export default User;
|
|
21
webapp/src/reducer/leaderboard.js
Normal file
21
webapp/src/reducer/leaderboard.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { useReducer } from 'react';
|
||||||
|
import { nextState } from '../util/StateHelper';
|
||||||
|
|
||||||
|
export const leaderboardInitialState = {
|
||||||
|
table: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function leaderboardReducer(state, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
|
||||||
|
case 'next':
|
||||||
|
return nextState(state, action);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw Error('LeaderboardReducer: Unknown action.type', action.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useLeaderboardReducer() {
|
||||||
|
return useReducer(leaderboardReducer, leaderboardInitialState);
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { useLocalStorage } from '../util/PersistentStorage'
|
import { useReducer } from 'react';
|
||||||
|
import { useLocalStorage } from '../util/PersistentStorage';
|
||||||
import { nextState } from '../util/StateHelper';
|
import { nextState } from '../util/StateHelper';
|
||||||
|
|
||||||
const Persistent = (() => {
|
const Persistent = (() => {
|
||||||
@ -33,9 +34,6 @@ export function pollingReducer(curntState, action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Polling = {
|
export default function usePollingReducer() {
|
||||||
reducer: pollingReducer,
|
return useReducer(pollingReducer, pollingInitialState);
|
||||||
initialState: pollingInitialState
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export default Polling
|
|
26
webapp/src/reducer/user.js
Normal file
26
webapp/src/reducer/user.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { useReducer } from 'react';
|
||||||
|
import { localeCompare } from '../util/Locale';
|
||||||
|
import { nextState } from '../util/StateHelper';
|
||||||
|
|
||||||
|
export const userInitialState = {
|
||||||
|
username: '',
|
||||||
|
|
||||||
|
isCurrentUser: function (otherUsername) {
|
||||||
|
return localeCompare(this.username, otherUsername)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function userReducer(state, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
|
||||||
|
case 'next':
|
||||||
|
return nextState(state, action);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw Error('Unknown action.type', action.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useUserReducer() {
|
||||||
|
return useReducer(userReducer, userInitialState);
|
||||||
|
}
|
@ -47,7 +47,7 @@ export default function usePolling(url, mode) {
|
|||||||
}, [url, mode, isFetching, cache, fetchData, delayID]);
|
}, [url, mode, isFetching, cache, fetchData, delayID]);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
cache, // API response
|
cache, // API responce
|
||||||
isFetching // true / false
|
isFetching // true / false
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user