Skip to content

Commit

Permalink
refactor: moving the createRouter logic out of the entry file (#413)
Browse files Browse the repository at this point in the history
* refactor: move the as much of the logic into the router's Wrap and InnerWrap rendering options

* refactor: move `FullPageLoadingSpinner` into its own independent component

* refactor: use a named fragment

* refactor: use the filename `main.css` instead of `index.css`

* refactor: use the filename `entry-app.tsx` instead of `app-entry.tsx`

* chore: update import
  • Loading branch information
SeanCassiere authored Aug 9, 2024
1 parent 033aa8b commit 9cf03f8
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 165 deletions.
2 changes: 1 addition & 1 deletion components.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"tsx": true,
"tailwind": {
"config": "tailwind.config.cjs",
"css": "src/index.css",
"css": "src/main.css",
"baseColor": "slate",
"cssVariables": true
},
Expand Down
159 changes: 0 additions & 159 deletions src/app-entry.tsx

This file was deleted.

20 changes: 19 additions & 1 deletion src/components/cache-buster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import * as React from "react";
import { compare } from "compare-versions";

import { useEventListener } from "@/lib/hooks/useEventListener";

type OnCacheClearFn = (callback?: () => void) => Promise<void>;

const CacheBusterContext = React.createContext<{
Expand Down Expand Up @@ -165,4 +167,20 @@ function useCacheBuster() {
return context;
}

export { CacheBuster, useCacheBuster };
function CacheDocumentFocusChecker() {
const documentRef = React.useRef<Document>(document);

const { checkCacheStatus } = useCacheBuster();

const onVisibilityChange = () => {
if (document.visibilityState === "visible") {
checkCacheStatus();
}
};

useEventListener("visibilitychange", onVisibilityChange, documentRef);

return null;
}

export { CacheBuster, CacheDocumentFocusChecker, useCacheBuster };
77 changes: 77 additions & 0 deletions src/entry-app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as React from "react";
import { RouterProvider } from "@tanstack/react-router";
import { useTranslation } from "react-i18next";
import { AuthProvider, useAuth } from "react-oidc-context";
import { Toaster } from "sonner";

import { CacheBuster } from "@/components/cache-buster";

import { useTernaryDarkMode } from "@/lib/hooks/useTernaryDarkMode";

import { APP_VERSION, IS_DEV } from "@/lib/utils/constants";

import "@/lib/config/i18next";

import { FullPageLoadingSpinner } from "@/routes/-components/full-screen-loading-spinner";

import { userManager } from "@/lib/config/oidc-client-ts";
import { createRouter } from "@/lib/config/tanstack-router";

const router = createRouter();

function App() {
const auth = useAuth();

React.useEffect(() => {
if (typeof auth.user === "undefined") return;

router.invalidate();
}, [auth.user]);

return typeof auth.user === "undefined" ? (
<FullPageLoadingSpinner />
) : (
<RouterProvider router={router} context={{ auth }} />
);
}

export default function UserApp() {
const { i18n } = useTranslation();
const theme = useTernaryDarkMode();

const dir = i18n.dir();

return (
<React.Suspense fallback={<FullPageLoadingSpinner />}>
<CacheBuster
loadingComponent={<FullPageLoadingSpinner />}
currentVersion={APP_VERSION}
isVerboseMode={IS_DEV}
isEnabled={IS_DEV === false}
reloadOnDowngrade
>
<AuthProvider userManager={userManager}>
<App />
</AuthProvider>
<Toaster
theme={theme.ternaryDarkMode}
dir={dir}
position="bottom-center"
className="toaster group"
toastOptions={{
classNames: {
toast:
"group toast group-[.toaster]:bg-[var(--toast-background)] group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
description: "group-[.toast]:text-muted-foreground",
actionButton:
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton:
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
},
}}
closeButton
/>
</CacheBuster>
</React.Suspense>
);
}
8 changes: 8 additions & 0 deletions src/lib/config/tanstack-query.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental";
import { QueryClient } from "@tanstack/react-query";

import { APP_VERSION } from "@/lib/utils/constants";

// Create a client for react-query
export const queryClient = new QueryClient({
defaultOptions: {
Expand All @@ -8,3 +11,8 @@ export const queryClient = new QueryClient({
},
},
});

broadcastQueryClient({
queryClient,
broadcastChannel: APP_VERSION,
});
67 changes: 67 additions & 0 deletions src/lib/config/tanstack-router.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from "react";
import { QueryClientProvider } from "@tanstack/react-query";
import {
createRouter as createTanStackRouter,
parseSearchWith,
stringifySearchWith,
} from "@tanstack/react-router";
import * as JSURL2 from "jsurl2";

import { CacheDocumentFocusChecker } from "@/components/cache-buster";
import { icons } from "@/components/ui/icons";
import { TooltipProvider } from "@/components/ui/tooltip";

import { GlobalDialogProvider } from "@/lib/context/modals";

import { queryClient } from "@/lib/config/tanstack-query";

import { routeTree } from "@/route-tree.gen";

export function createRouter() {
const router = createTanStackRouter({
routeTree,
defaultPreload: "intent",
defaultPreloadStaleTime: 0,
defaultViewTransition: true,
defaultPendingComponent: function RouterPendingComponent() {
<div className="grid min-h-full w-full place-items-center">
<icons.Loading className="h-24 w-24 animate-spin text-foreground" />
</div>;
},
parseSearch: parseSearchWith((value) => JSURL2.parse(value)),
stringifySearch: stringifySearchWith(
(value) => JSURL2.stringify(value),
(value) => JSURL2.parse(value)
),
context: {
queryClient,
auth: undefined!, // will be set by an AuthWrapper
},
trailingSlash: "never",
Wrap: function ({ children }) {
return (
<QueryClientProvider client={queryClient}>
<GlobalDialogProvider>
<TooltipProvider>{children}</TooltipProvider>
</GlobalDialogProvider>
</QueryClientProvider>
);
},
InnerWrap: function ({ children }) {
return (
<React.Fragment>
<CacheDocumentFocusChecker />
{children}
</React.Fragment>
);
},
});

return router;
}

declare module "@tanstack/react-router" {
interface Register {
router: ReturnType<typeof createRouter>;
}
}
File renamed without changes.
6 changes: 3 additions & 3 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from "react";
import ReactDOM from "react-dom/client";

import App from "./app-entry";
import UserApp from "./entry-app";

import "./index.css";
import "./main.css";

const documentElement = document.getElementById("root");

Expand All @@ -13,6 +13,6 @@ if (!documentElement) {

ReactDOM.createRoot(documentElement).render(
<React.StrictMode>
<App />
<UserApp />
</React.StrictMode>
);
9 changes: 9 additions & 0 deletions src/routes/-components/full-screen-loading-spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { icons } from "@/components/ui/icons";

export function FullPageLoadingSpinner() {
return (
<div className="grid min-h-full w-full place-items-center">
<icons.Loading className="h-24 w-24 animate-spin text-foreground" />
</div>
);
}
Loading

0 comments on commit 9cf03f8

Please sign in to comment.