TanStack router and pglite provider

The project used TanStack router to handle client routing:

npm install @tanstack/react-router

TanStack router is fully type-safe React router with built-in data fetching, stale-while revalidate caching and first-class search-param APIs.

The main entry point is defined inside __root.tsx. It uses createRootRoute and contains the shared layout and providers:

export const Route = createRootRoute({
  component: RootComponent,
});

function RootComponent() {
  return (
    <div className="max-w-xl mx-auto pt-12 bg-theme-background">
      <Outlet />
    </div>
  );
}

Using pglite on the client requires wrapping the root component with PgliteProvider (from @electric-sql/pglite-react):

pnpm add @electric-sql/pglite-react

Furthermore, we also define a custom context provider to access the Pglite service with drizzle (for building queries).

We use loader to provide the Pglite service to the root component:

export const Route = createRootRoute({
  component: RootComponent,
  loader: () => RuntimeClient.runPromise(Pglite),
});

function RootComponent() {
  const { client } = Route.useLoaderData();
  return (
    <PGliteProvider db={client}>
      <div className="max-w-xl mx-auto pt-12 bg-theme-background">
        <Outlet />
      </div>
    </PGliteProvider>
  );
}

We define the provider for drizzle in a separate use-pglite-drizzle.ts file:

import { Context } from "effect";
import { createContext, useContext } from "react";
import { Pglite } from "~/services/pglite";

export const PgliteDrizzleContext = createContext<
  Context.Tag.Service<typeof Pglite>["orm"] | null
>(null);

export const usePgliteDrizzle = () => {
  const orm = useContext(PgliteDrizzleContext);
  if (orm === null) {
    throw new Error(
      "usePgliteDrizzle must be used within PgliteDrizzleProvider"
    );
  }
  return orm;
};

We then provide this as well inside __root.tsx:

export const Route = createRootRoute({
  component: RootComponent,
  loader: () => RuntimeClient.runPromise(Pglite),
});

function RootComponent() {
  const { client, orm } = Route.useLoaderData();
  return (
    <PgliteDrizzleContext.Provider value={orm}>
      <PGliteProvider db={client}>
        <div className="max-w-xl mx-auto pt-12 bg-theme-background">
          <Outlet />
        </div>
      </PGliteProvider>
    </PgliteDrizzleContext.Provider>
  );
}

With this configuration we can access both client and orm everywhere inside the application.