chore: react-query v5

This commit is contained in:
mattia
2025-07-07 21:25:48 +02:00
parent 43474b85bf
commit 1abdbac3d0
6 changed files with 63 additions and 85 deletions

39
package-lock.json generated
View File

@@ -29,7 +29,7 @@
"@fontsource/roboto": "^5.1.1", "@fontsource/roboto": "^5.1.1",
"@mui/icons-material": "^7.2.0", "@mui/icons-material": "^7.2.0",
"@mui/material": "^7.2.0", "@mui/material": "^7.2.0",
"@tanstack/react-query": "^4.0.0", "@tanstack/react-query": "^5.0.0",
"@ts-rest/react-query": "^3.51.0", "@ts-rest/react-query": "^3.51.0",
"@types/cors": "^2.8.17", "@types/cors": "^2.8.17",
"@types/express": "^4.0.0", "@types/express": "^4.0.0",
@@ -1793,9 +1793,9 @@
} }
}, },
"node_modules/@tanstack/query-core": { "node_modules/@tanstack/query-core": {
"version": "4.40.0", "version": "5.81.5",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.40.0.tgz", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.81.5.tgz",
"integrity": "sha512-7MJTtZkCSuehMC7IxMOCGsLvHS3jHx4WjveSrGsG1Nc1UQLjaFwwkpLA2LmPfvOAxnH4mszMOBFD6LlZE+aB+Q==", "integrity": "sha512-ZJOgCy/z2qpZXWaj/oxvodDx07XcQa9BF92c0oINjHkoqUPsmm3uG08HpTaviviZ/N9eP1f9CM7mKSEkIo7O1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
@@ -1804,31 +1804,20 @@
} }
}, },
"node_modules/@tanstack/react-query": { "node_modules/@tanstack/react-query": {
"version": "4.40.1", "version": "5.81.5",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.40.1.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.81.5.tgz",
"integrity": "sha512-mgD07S5N8e5v81CArKDWrHE4LM7HxZ9k/KLeD3+NUD9WimGZgKIqojUZf/rXkfAMYZU9p0Chzj2jOXm7xpgHHQ==", "integrity": "sha512-lOf2KqRRiYWpQT86eeeftAGnjuTR35myTP8MXyvHa81VlomoAWNEd8x5vkcAfQefu0qtYCvyqLropFZqgI2EQw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/query-core": "4.40.0", "@tanstack/query-core": "5.81.5"
"use-sync-external-store": "^1.2.0"
}, },
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/tannerlinsley" "url": "https://github.com/sponsors/tannerlinsley"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react": "^18 || ^19"
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-native": "*"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
} }
}, },
"node_modules/@tanstack/react-table": { "node_modules/@tanstack/react-table": {
@@ -5303,16 +5292,6 @@
"browserslist": ">= 4.21.0" "browserslist": ">= 4.21.0"
} }
}, },
"node_modules/use-sync-external-store": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
"integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/utils-merge": { "node_modules/utils-merge": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",

View File

@@ -23,7 +23,7 @@
"@fontsource/roboto": "^5.1.1", "@fontsource/roboto": "^5.1.1",
"@mui/icons-material": "^7.2.0", "@mui/icons-material": "^7.2.0",
"@mui/material": "^7.2.0", "@mui/material": "^7.2.0",
"@tanstack/react-query": "^4.0.0", "@tanstack/react-query": "^5.0.0",
"@ts-rest/react-query": "^3.51.0", "@ts-rest/react-query": "^3.51.0",
"@types/cors": "^2.8.17", "@types/cors": "^2.8.17",
"@types/express": "^4.0.0", "@types/express": "^4.0.0",

View File

@@ -9,6 +9,7 @@ import { StrictMode } from "react";
import { ThemeProvider } from "@emotion/react"; import { ThemeProvider } from "@emotion/react";
import { CssBaseline } from "@mui/material"; import { CssBaseline } from "@mui/material";
import theme from "./theme"; import theme from "./theme";
import { tsr } from "./client";
import { SessionDetails } from "./SessionDetails"; import { SessionDetails } from "./SessionDetails";
import { Root } from "./Root"; import { Root } from "./Root";
@@ -20,6 +21,7 @@ export function App() {
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
<CssBaseline /> <CssBaseline />
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<tsr.ReactQueryProvider>
<BrowserRouter> <BrowserRouter>
<Routes> <Routes>
<Route path="/" element={<Root />}> <Route path="/" element={<Root />}>
@@ -31,6 +33,7 @@ export function App() {
</Route> </Route>
</Routes> </Routes>
</BrowserRouter> </BrowserRouter>
</tsr.ReactQueryProvider>
</QueryClientProvider> </QueryClientProvider>
</ThemeProvider> </ThemeProvider>
</StrictMode> </StrictMode>

View File

@@ -1,5 +1,5 @@
import { useParams } from "react-router"; import { useParams } from "react-router";
import { client } from "./client"; import { tsr } from "./client";
import { import {
Autocomplete, Autocomplete,
Button, Button,
@@ -16,12 +16,7 @@ import {
TextField, TextField,
Typography, Typography,
} from "@mui/material"; } from "@mui/material";
import { import { Fragment, useCallback, useMemo, useState } from "react";
Fragment,
useCallback,
useMemo,
useState,
} from "react";
import { import {
createMRTColumnHelper, createMRTColumnHelper,
MaterialReactTable, MaterialReactTable,
@@ -41,8 +36,11 @@ export function SessionDetails() {
throw new Error("session id is required"); throw new Error("session id is required");
} }
const getSessionQuery = client.getSession.useQuery(["session", sessionId], { const getSessionQuery = tsr.getSession.useQuery({
queryKey: ["session", sessionId],
queryData: {
params: { id: sessionId }, params: { id: sessionId },
},
}); });
const columns = useMemo( const columns = useMemo(
@@ -101,17 +99,15 @@ export function SessionDetails() {
[] []
); );
const getCategoriesQuery = client.getCategories.useQuery( const getCategoriesQuery = tsr.getCategories.useQuery({
["get-categories", sessionId], queryKey: ["get-categories", sessionId],
{ enabled: isExportDialogOpen,
queryData: {
query: { query: {
sessionId, sessionId,
}, },
}, },
{ });
enabled: isExportDialogOpen,
}
);
const [selectedCategory, setSelectedCategory] = useState(""); const [selectedCategory, setSelectedCategory] = useState("");
const handleSelectedCategoryChange = useCallback( const handleSelectedCategoryChange = useCallback(
@@ -123,18 +119,13 @@ export function SessionDetails() {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const onExport = useCallback(() => { const onExport = useCallback(() => {
client.getEntries tsr.getEntries
.fetchQuery( .query({
queryClient, params: {
["get-entries", sessionId, selectedCategory], sessionId,
{
params: { sessionId },
query: { category: selectedCategory },
}, },
{ query: { category: selectedCategory },
meta: { causeDownload: true }, })
}
)
.then((data) => { .then((data) => {
const json = JSON.stringify(data.body, null, 2); const json = JSON.stringify(data.body, null, 2);
const blob = new Blob([json], { type: "application/json" }); const blob = new Blob([json], { type: "application/json" });
@@ -162,13 +153,13 @@ export function SessionDetails() {
</Typography> </Typography>
<Typography variant="h5" component="div"> <Typography variant="h5" component="div">
Game:{" "} Game:{" "}
{getSessionQuery.status === "loading" {getSessionQuery.status === "pending"
? "..." ? "..."
: getSessionQuery.data.body.game_name} : getSessionQuery.data.body.game_name}
</Typography> </Typography>
<Typography variant="body2"> <Typography variant="body2">
Version{" "} Version{" "}
{getSessionQuery.status === "loading" {getSessionQuery.status === "pending"
? "..." ? "..."
: getSessionQuery.data.body.version} : getSessionQuery.data.body.version}
</Typography> </Typography>

View File

@@ -1,4 +1,4 @@
import { client } from "./client"; import { tsr } from "./client";
import { import {
MaterialReactTable, MaterialReactTable,
MRT_ColumnFiltersState, MRT_ColumnFiltersState,
@@ -15,6 +15,7 @@ import { Typography } from "@mui/material";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { shortGuidsAtom } from "./configuration"; import { shortGuidsAtom } from "./configuration";
import { formatGuid } from "./guid"; import { formatGuid } from "./guid";
import { keepPreviousData } from "@tanstack/react-query";
export function Sessions() { export function Sessions() {
const [paginationState, setPaginationState] = useState<MRT_PaginationState>({ const [paginationState, setPaginationState] = useState<MRT_PaginationState>({
@@ -25,9 +26,10 @@ export function Sessions() {
[] []
); );
const getSessionsQuery = client.getSessions.useQuery( const getSessionsQuery = tsr.getSessions.useQuery({
["sessions", { columnFilters, paginationState }], queryKey: ["sessions", { columnFilters, paginationState }],
{ placeholderData: keepPreviousData,
queryData: {
query: { query: {
skip: paginationState.pageIndex * paginationState.pageSize, skip: paginationState.pageIndex * paginationState.pageSize,
count: paginationState.pageSize, count: paginationState.pageSize,
@@ -36,23 +38,20 @@ export function Sessions() {
| undefined, | undefined,
}, },
}, },
{ });
keepPreviousData: true,
}
);
return getSessionsQuery.status === "error" ? ( return getSessionsQuery.status === "error" ? (
<p>Error</p> <p>Error</p>
) : ( ) : (
<SessionsTable <SessionsTable
data={ data={
getSessionsQuery.status === "loading" getSessionsQuery.status === "pending"
? { total: 0, sessions: [] } ? { total: 0, sessions: [] }
: getSessionsQuery.data.body : getSessionsQuery.data.body
} }
paginationState={paginationState} paginationState={paginationState}
setPaginationState={setPaginationState} setPaginationState={setPaginationState}
isLoading={getSessionsQuery.status === "loading"} isLoading={getSessionsQuery.status === "pending"}
isRefetching={getSessionsQuery.isRefetching} isRefetching={getSessionsQuery.isRefetching}
columnFilters={columnFilters} columnFilters={columnFilters}
setColumnFilters={setColumnFilters} setColumnFilters={setColumnFilters}
@@ -89,7 +88,11 @@ function SessionsTable({
row: { row: {
original: { save_id }, original: { save_id },
}, },
}) => <Typography variant="body2">{formatGuid(save_id, shortGuids)}</Typography>, }) => (
<Typography variant="body2">
{formatGuid(save_id, shortGuids)}
</Typography>
),
}, },
{ {
accessorKey: "id", accessorKey: "id",
@@ -99,7 +102,9 @@ function SessionsTable({
row: { row: {
original: { id }, original: { id },
}, },
}) => <Typography variant="body2">{formatGuid(id, shortGuids)}</Typography>, }) => (
<Typography variant="body2">{formatGuid(id, shortGuids)}</Typography>
),
}, },
{ {
accessorKey: "game_name", accessorKey: "game_name",

View File

@@ -1,5 +1,5 @@
// client.ts // client.ts
import { initQueryClient } from "@ts-rest/react-query"; import { initTsrReactQuery } from "@ts-rest/react-query/v5";
import { contract } from "../common/contract"; import { contract } from "../common/contract";
export const serverRoot = export const serverRoot =
@@ -7,7 +7,7 @@ export const serverRoot =
? "http://localhost:9283" ? "http://localhost:9283"
: window.location.protocol + "//" + window.location.host; : window.location.protocol + "//" + window.location.host;
export const client = initQueryClient(contract, { export const tsr = initTsrReactQuery(contract, {
baseUrl: serverRoot, baseUrl: serverRoot,
baseHeaders: {}, baseHeaders: {},
}); });