Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage with drizzle in React? #518

Open
JanChodorowski opened this issue Feb 3, 2025 · 4 comments
Open

Usage with drizzle in React? #518

JanChodorowski opened this issue Feb 3, 2025 · 4 comments

Comments

@JanChodorowski
Copy link

JanChodorowski commented Feb 3, 2025

const client = await PGlite.create({
  dataDir: "idb://pgdata",
  extensions: { live },
});

const db = drizzle({ client, schema: { usersTable } });

Is it possible to make PGliteProvider accept drizzle and make it work with useLiveQuery? The usePGlite works, the types are wrong though.

@SemStassen
Copy link

SemStassen commented Feb 3, 2025

I created my own custom wrapper for useLiveQuery that uses injected drizzle statements. The final hook actually ended up being quite simple!

/**
/* Hook
/**
import { useLiveIncrementalQuery } from "@electric-sql/pglite-react";
import type { Query } from "drizzle-orm";

export const useSubscription = (query: Query, key: string) => {
  const res = useLiveIncrementalQuery(query.sql, query.params, key);

  if (!res) {
    return {
      status: "loading",
    };
  }

  return {
    status: "success",
    data: res.rows,
  };
};
/**
/* Usage
/**
const me = useSubscription(
  db.query.usersTable
    .findFirst({
      where: (users, { eq }) => eq(users.uuid, userUuid),
    })
    .toSQL(),
  "uuid",
);

Hope this helps!

EDIT:

After fooling around a bit more. I managed to keep the drizzle type-inference!

interface LoadingState {
  status: "loading";
}

interface SuccessState<T> {
  status: "success";
  data: T[];
}

type SubscriptionResult<T> = LoadingState | SuccessState<T>;

export const useSubscription = <T>(
  query: PgRelationalQuery<T>,
  key: string,
): SubscriptionResult<T> => {
  const sql = query.toSQL();

  const res = useLiveIncrementalQuery(sql.sql, sql.params, key);
  if (!res) {
    return {
      status: "loading",
    };
  }

  return {
    status: "success",
    data: res.rows as T[],
  };
};

Happy coding!

@JanChodorowski
Copy link
Author

@SemStassen The hook looks clever! I can't get it all to work though. How do you feed your PGliteProvider? Or are you using db from drizzle directly?

@SemStassen
Copy link

@JanChodorowski

The db is indeed from drizzle directly.

However I do still expose the PG instance through the PGliteProvider.

export const pg = await PGliteWorker.create(new PGWorker(), {
  extensions: {
    live,
    sync: electricSync(),
  },
});

/**
/* This is the drizzle-orm instance we use in the useSubscription hook!
/**
export const db = drizzle({ client: pg, schema: schema });

export const MasonPGliteProvider = ({
  children,
}: { children: React.ReactNode }) => {
  return <PGliteProvider db={pg}>{children}</PGliteProvider>;
};

Hope this helps!

@MiguelsPizza
Copy link

just chiming in to say there is a really decent lib published for this

https://jsr.io/@makisuo/pglite-drizzle

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants