Skip to content

Commit

Permalink
chore(nodejs): upgrade to React Query v5 (#1156)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhess authored Apr 10, 2024
2 parents dba7796 + 3726e3f commit f13c213
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 186 deletions.
4 changes: 2 additions & 2 deletions orval.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const useQueryPost: {
})
);

// We disable caching by default, to avoid displaying stale data.
const queryOpts: UseQueryOptions = { cacheTime: 0 };
// gc immediately, to disable showing cached data.
const queryOpts: UseQueryOptions = { gcTime: 0 };

export default defineConfig({
"primer-api": {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
"@hookform/resolvers": "^3.3.4",
"@neodrag/react": "^2.0.4",
"@orval/core": "^6.26.0",
"@tanstack/react-query": "^4.36.1",
"@tanstack/react-query-devtools": "^4.36.1",
"@tanstack/react-query": "^5.29.0",
"@tanstack/react-query-devtools": "^5.29.0",
"@types/deep-equal": "^1.0.4",
"@zxch3n/tidy": "github:hackworthltd/tidy#e07fdef2ae7bf593701817113dd47b4cd56c7a97",
"axios": "^1.6.8",
Expand Down
75 changes: 18 additions & 57 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

94 changes: 12 additions & 82 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,19 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { CookiesProvider, useCookies } from "react-cookie";
import { CookieSetOptions } from "universal-cookie";
import { v4 as uuidv4 } from "uuid";
import { WrenchScrewdriverIcon } from "@heroicons/react/24/outline";
import { Resizable } from "re-resizable";

import "@/index.css";

import { ChooseSession, Edit, NoMatch } from "@/components";
import { DevOptions } from "@/components/Edit";

// This ensures that we don't unnecessarily load the tools in production.
// https://tanstack.com/query/v4/docs/react/devtools#devtools-in-production
const ReactQueryDevtoolsPanel = lazy(() =>
import("@tanstack/react-query-devtools/build/lib/index.prod.js").then(
//
// Ref:
// https://tanstack.com/query/latest/docs/framework/react/devtools#devtools-in-production
const ReactQueryDevtools = lazy(() =>
import("@tanstack/react-query-devtools/build/modern/production.js").then(
(d) => ({
default: d.ReactQueryDevtoolsPanel,
default: d.ReactQueryDevtools,
})
)
);
Expand All @@ -37,16 +36,7 @@ const idCookieOptions = (path: string): CookieSetOptions => {

const App = (): JSX.Element => {
const [cookies, setCookie] = useCookies(["id"]);
const [enableDevtools, setEnableDevtools] = useState(import.meta.env.DEV);
const [devtoolsOpen, setDevtoolsOpen] = useState(false);

const devToolsMinHeight = 250;
const devToolsMaxHeight = 500;
const [devOpts, setDevOpts] = useState<DevOptions>({
showIDs: false,
inlineLabels: false,
alwaysShowLabels: true,
});
const [showDevtools, setShowDevtools] = useState(import.meta.env.DEV);

useEffect(() => {
if (!cookies.id) {
Expand All @@ -60,47 +50,24 @@ const App = (): JSX.Element => {

useEffect(() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
window.toggleDevtools =
// This comment forces a line break to limit the scope of `@ts-ignore`.
() => setEnableDevtools((old) => !old);
// @ts-expect-error
window.toggleDevtools = () => setShowDevtools((old) => !old);
}, []);

return (
<CookiesProvider>
<BrowserRouter>
<QueryClientProvider client={queryClient}>
{enableDevtools && (
{showDevtools && (
<Suspense fallback={null}>
<button
className="absolute right-0 z-50 p-4"
onClick={() => setDevtoolsOpen((old) => !old)}
>
<WrenchScrewdriverIcon className="h-10 fill-grey-primary"></WrenchScrewdriverIcon>
</button>
{devtoolsOpen && (
<Resizable
enable={{ bottom: true }}
defaultSize={{ height: devToolsMinHeight, width: "100%" }}
className="fixed grid grid-cols-[minmax(0,2fr)_1fr]"
minHeight={devToolsMinHeight}
maxHeight={devToolsMaxHeight}
>
<ReactQueryDevtoolsPanel
style={{ height: "inherit", maxHeight: devToolsMaxHeight }}
setIsOpen={setDevtoolsOpen}
onDragStart={(_) => {}}
/>
<DevMenu opts={devOpts} set={setDevOpts} />
</Resizable>
)}
<ReactQueryDevtools position="top" buttonPosition="top-right" />
</Suspense>
)}
<Routes>
<Route path="/" element={<Navigate to="/sessions" />} />
<Route path="/sessions">
<Route index element={<ChooseSession />} />
<Route path=":sessionId" element={<Edit {...devOpts} />} />
<Route path=":sessionId" element={<Edit />} />
</Route>
<Route path="*" element={<NoMatch />} />
</Routes>
Expand All @@ -110,41 +77,4 @@ const App = (): JSX.Element => {
);
};

const DevMenu = (p: { opts: DevOptions; set: (opts: DevOptions) => void }) => (
<div className="bg-blue-primary pl-1 text-white-primary">
<div>
<input
type="checkbox"
id="showIDs"
checked={p.opts.showIDs}
onChange={(e) => p.set({ ...p.opts, showIDs: e.target.checked })}
className="mr-1"
/>
<label htmlFor="showIDs">show node IDs</label>
</div>
<div>
<input
type="checkbox"
id="alwaysShowLabels"
checked={p.opts.alwaysShowLabels}
onChange={(e) =>
p.set({ ...p.opts, alwaysShowLabels: e.target.checked })
}
className="mr-1"
/>
<label htmlFor="alwaysShowLabels">always show labels</label>
</div>
<div>
<input
type="checkbox"
id="inlineLabels"
checked={p.opts.inlineLabels}
onChange={(e) => p.set({ ...p.opts, inlineLabels: e.target.checked })}
className="mr-1"
/>
<label htmlFor="inlineLabels">inline labels</label>
</div>
</div>
);

export default App;
8 changes: 6 additions & 2 deletions src/components/ChooseSession/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ const ChooseSession = (): JSX.Element => {
const deleteSession = useDeleteSession({
mutation: {
onSuccess: () =>
queryClient.invalidateQueries(getGetSessionListQueryKey()),
queryClient.invalidateQueries({
queryKey: getGetSessionListQueryKey(),
}),
},
});
const { data } = useGetSessionList({
Expand Down Expand Up @@ -57,7 +59,9 @@ const ChooseSession = (): JSX.Element => {
const newSession = useCreateSession({
mutation: {
onSuccess: (newSessionID: Uuid) => {
queryClient.invalidateQueries(getGetSessionListQueryKey());
queryClient.invalidateQueries({
queryKey: getGetSessionListQueryKey(),
});
navigate(`/sessions/${newSessionID}`);
},
},
Expand Down
51 changes: 26 additions & 25 deletions src/components/Edit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,17 @@ export type DevOptions = {
alwaysShowLabels: boolean;
};

const Edit = (devOpts: DevOptions): JSX.Element => {
const Edit = (): JSX.Element => {
const params = useParams();
const sessionId = params["sessionId"];

// Temporary until these toggles are re-enabled.
const devOpts: DevOptions = {
showIDs: false,
inlineLabels: false,
alwaysShowLabels: false,
};

if (!sessionId) {
return (
<Error string={"No sessionId parameter: " + JSON.stringify(params)} />
Expand All @@ -74,33 +81,24 @@ const Edit = (devOpts: DevOptions): JSX.Element => {
// This hook is *technically* conditional.
// But if the condition above fails, then the app is broken anyway.
// eslint-disable-next-line react-hooks/rules-of-hooks
const queryRes = useGetProgram(sessionId);
const { isPending, isError, data, error } = useGetProgram(sessionId);

if (queryRes.error) {
if (isError) {
return (
<Error
string={
"Failed to get program from backend: " +
JSON.stringify(queryRes.error)
}
/>
<Error string={"Failed to get program from backend: " + error.message} />
);
}

// This state will appear on every load, usually only very briefly,
// and we choose to just show nothing.
if (queryRes.isLoading) {
} else if (isPending) {
// This state will appear on every load, usually only very briefly,
// and we choose to just show nothing.
return <></>;
}

// At this point, we have successfully received an initial program.
return (
<AppProg
initialProg={queryRes.data}
{...{ sessionId }}
devOpts={devOpts}
></AppProg>
);
} else
return (
<AppProg
initialProg={data}
{...{ sessionId }}
devOpts={devOpts}
></AppProg>
);
};

const AppProg = (p: {
Expand Down Expand Up @@ -190,7 +188,10 @@ const useInvalidateOnChange = <TData, TError>(
useEffect(
() => {
(async () =>
await queryClient.invalidateQueries(res.queryKey, { exact: true }))();
await queryClient.invalidateQueries({
queryKey: res.queryKey,
exact: true,
}))();
},
// We stringify the queryKey as a poor-man's deep equality check,
// since the orval generated bindings to react-query construct a
Expand Down
Loading

0 comments on commit f13c213

Please sign in to comment.