react query
This commit is contained in:
parent
2a94a47a96
commit
25a3adea2a
25
tank-frontend/package-lock.json
generated
25
tank-frontend/package-lock.json
generated
|
@ -8,6 +8,7 @@
|
|||
"name": "tank-frontend",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^5.29.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-use-websocket": "^4.8.1"
|
||||
|
@ -1188,6 +1189,30 @@
|
|||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@tanstack/query-core": {
|
||||
"version": "5.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.29.0.tgz",
|
||||
"integrity": "sha512-WgPTRs58hm9CMzEr5jpISe8HXa3qKQ8CxewdYZeVnA54JrPY9B1CZiwsCoLpLkf0dGRZq+LcX5OiJb0bEsOFww==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-query": {
|
||||
"version": "5.29.2",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.29.2.tgz",
|
||||
"integrity": "sha512-nyuWILR4u7H5moLGSiifLh8kIqQDLNOHGuSz0rcp+J75fNc8aQLyr5+I2JCHU3n+nJrTTW1ssgAD8HiKD7IFBQ==",
|
||||
"dependencies": {
|
||||
"@tanstack/query-core": "5.29.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^5.29.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-use-websocket": "^4.8.1"
|
||||
|
|
|
@ -44,8 +44,8 @@ export default function App() {
|
|||
<ClientScreen logout={logout} theme={theme} playerId={nameId.id}/>
|
||||
{nameId.name === '' && <JoinForm setNameId={setNameId} clientId={nameId.id}/>}
|
||||
<Row className='GadgetRows'>
|
||||
{isLoggedIn && <Controls playerId={nameId.id} logout={logout}/>}
|
||||
{isLoggedIn && <PlayerInfo playerId={nameId.id} logout={logout}/>}
|
||||
{isLoggedIn && <Controls playerId={nameId.id}/>}
|
||||
{isLoggedIn && <PlayerInfo playerId={nameId.id}/>}
|
||||
<Scoreboard/>
|
||||
</Row>
|
||||
</Column>;
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
import './Controls.css';
|
||||
import useWebSocket, {ReadyState} from 'react-use-websocket';
|
||||
import {useEffect} from 'react';
|
||||
import {Guid} from "./Guid.ts";
|
||||
|
||||
export default function Controls({playerId, logout}: {
|
||||
playerId: string,
|
||||
logout: () => void
|
||||
}) {
|
||||
export default function Controls({playerId}: { playerId: Guid }) {
|
||||
const url = new URL('controls', import.meta.env.VITE_TANK_WS);
|
||||
url.searchParams.set('playerId', playerId);
|
||||
|
||||
const {
|
||||
sendMessage,
|
||||
getWebSocket,
|
||||
readyState
|
||||
} = useWebSocket(url.toString(), {
|
||||
onError: logout,
|
||||
shouldReconnect: () => true,
|
||||
});
|
||||
|
||||
|
|
|
@ -1,43 +1,40 @@
|
|||
import {useEffect, useState} from 'react';
|
||||
import {Player, getPlayer} from './serverCalls';
|
||||
import {useQuery} from '@tanstack/react-query'
|
||||
import {Player} from './serverCalls';
|
||||
import {Guid} from "./Guid.ts";
|
||||
import Column from "./components/Column.tsx";
|
||||
|
||||
export default function PlayerInfo({playerId, logout}: {
|
||||
playerId: Guid,
|
||||
logout: () => void
|
||||
}) {
|
||||
const [player, setPlayer] = useState<Player | null>();
|
||||
export default function PlayerInfo({playerId}: { playerId: Guid }) {
|
||||
const query = useQuery({
|
||||
queryKey: ['player'],
|
||||
refetchInterval: 1000,
|
||||
queryFn: async () => {
|
||||
const url = new URL('/player', import.meta.env.VITE_TANK_API);
|
||||
url.searchParams.set('id', playerId);
|
||||
|
||||
useEffect(() => {
|
||||
const refresh = () => {
|
||||
getPlayer(playerId).then(response => {
|
||||
if (response.successResult)
|
||||
setPlayer(response.successResult);
|
||||
else
|
||||
logout();
|
||||
});
|
||||
};
|
||||
|
||||
const timer = setInterval(refresh, 5000);
|
||||
return () => clearInterval(timer);
|
||||
}, [playerId]);
|
||||
const response = await fetch(url, {method: 'GET'});
|
||||
if (!response.ok)
|
||||
throw new Error(`response failed with code ${response.status} (${response.status})${await response.text()}`)
|
||||
return await response.json() as Player;
|
||||
}
|
||||
});
|
||||
|
||||
return <Column className='PlayerInfo'>
|
||||
<h3>
|
||||
{player ? `Playing as ${player?.name}` : 'loading...'}
|
||||
{query.isPending && 'loading...'}
|
||||
{query.isSuccess && `Playing as ${query.data.name}`}
|
||||
</h3>
|
||||
<table>
|
||||
{query.isError && <p>{query.error.message}</p>}
|
||||
{query.isSuccess && <table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>kills:</td>
|
||||
<td>{player?.scores.kills}</td>
|
||||
<td>{query.data?.scores?.kills ?? '?'}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>deaths:</td>
|
||||
<td>{player?.scores.deaths}</td>
|
||||
<td>{query.data?.scores?.deaths ?? '?'}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</table>}
|
||||
</Column>;
|
||||
}
|
||||
|
|
|
@ -1,28 +1,31 @@
|
|||
import {getScores, Player} from "./serverCalls.tsx";
|
||||
import {useEffect, useState} from "react";
|
||||
import {Player} from "./serverCalls.tsx";
|
||||
import DataTable from "./components/DataTable.tsx";
|
||||
import {useQuery} from "@tanstack/react-query";
|
||||
|
||||
function numberSorter(a: number, b: number) {
|
||||
return b - a;
|
||||
}
|
||||
|
||||
export default function Scoreboard({}: {}) {
|
||||
const [players, setPlayers] = useState<Player[]>([]);
|
||||
const query = useQuery({
|
||||
queryKey: ['scores'],
|
||||
refetchInterval: 1000,
|
||||
queryFn: async () => {
|
||||
const url = new URL('/scores', import.meta.env.VITE_TANK_API);
|
||||
const response = await fetch(url, {method: 'GET'});
|
||||
if (!response.ok)
|
||||
throw new Error(`response failed with code ${response.status} (${response.status})${await response.text()}`)
|
||||
return await response.json() as Player[];
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const refresh = () => {
|
||||
getScores().then(value => {
|
||||
if (value.successResult)
|
||||
setPlayers(value.successResult);
|
||||
});
|
||||
};
|
||||
|
||||
const timer = setInterval(refresh, 5000);
|
||||
return () => clearInterval(timer);
|
||||
}, [players]);
|
||||
if (query.isError)
|
||||
return <p>{query.error.message}</p>;
|
||||
if (query.isPending)
|
||||
return <p>loading...</p>;
|
||||
|
||||
return <DataTable
|
||||
data={players}
|
||||
data={query.data}
|
||||
columns={[
|
||||
{field: 'name'},
|
||||
{
|
||||
|
|
|
@ -2,9 +2,14 @@ import React from 'react';
|
|||
import {createRoot} from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from "./App.tsx";
|
||||
import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
|
||||
|
||||
const queryClient = new QueryClient()
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<App/>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<App/>
|
||||
</QueryClientProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
|
|
@ -44,15 +44,3 @@ export function postPlayer({name, id}: NameId) {
|
|||
|
||||
return fetchTyped<NameId>({url, method: 'POST'});
|
||||
}
|
||||
|
||||
export function getPlayer(id: Guid) {
|
||||
const url = new URL('/player', import.meta.env.VITE_TANK_API);
|
||||
url.searchParams.set('id', id);
|
||||
|
||||
return fetchTyped<Player>({url, method: 'GET'});
|
||||
}
|
||||
|
||||
export function getScores() {
|
||||
const url = new URL('/scores', import.meta.env.VITE_TANK_API);
|
||||
return fetchTyped<Player[]>({url, method: 'GET'});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue