aspen-cloud/triplit

Simplify Queries by passing client / Query

sgup opened this issue · 4 comments

sgup commented

In a query like this:

useQuery(
  triplit,
  triplit
    .query('directors')
    .include('allFilms', (rel) => rel('allFilms').include('actors').build())
);

In the ClientQueryBuilder class, why not expose the current Q Query and a reference to the client, so it could be simplified further to:

useQuery(
  triplit
    .query('directors')
    .include('allFilms', (rel) => rel('allFilms').include('actors'))
    // no build() or client ref required as it can be accessed from class
);

& since useQuery is a react-specific hook, and thus made specifically to provide an easier/better interface over triplit, it would make sense to go further react-y and use the context/provider pattern:

import { TriplitProvider } from '@triplit/react'

function App() {
  <TriplitProvider client={triplitClient}>
    <div>
      <h1>My Triplit App</h1>
    </div>
  </TriplitProvider>
}

& in the components:

useQuery(
  "directors",
  (q) => q.include("allFilms", (rel) => rel("allFilms").include("actors"))
  // triplit client is provided by the TriplitProvider
);

Final Diff:

useQuery(
  triplit,
  triplit
    .query('directors')
    .include('allFilms', (rel) => rel('allFilms').include('actors').build())
);
  
// vs 
  
useQuery(
  "directors",
  (q) => q.include("allFilms", (rel) => rel("allFilms").include("actors"))
);

I like your idea! Especially the query builder callback ((q) => q.include(allFilms"....) Have you tried implementing this in "userland"? Seemingly only thing that would need to change is the @triplit/react package.

// no build() or client ref required as it can be accessed from class

Yeah, I'd also like to see this simplified syntax across all frameworks (svelte, etc) that use useQuery!

@sgup Maybe you could add a PR to add the abridged syntax version to the core ?

Also think this looks way more useable.
The only annoying part here is, that you have to bind the client somehow to useQuery.
I made a example implementation for the vue package here

import { TriplitClient, Schema as S, ClientSchema } from '@triplit/client';
import { useTriplit } from '@triplit/vue';

const schema = {
  todos: {
    schema: S.Schema({
      id: S.Id(),
      text: S.String(),
      complete: S.Boolean(),
    }),
  },
} satisfies ClientSchema;

const client = new TriplitClient({
  serverUrl: YOUR_SERVER_URL,
  token: YOUR_TOKEN,
  schema
});

const { useQuery } = useTriplit(client);

const { fetching, results, error, updateQuery } = useQuery(
  'todos',
  (q) => q.where('complete', '!=', false)
);

But you can still use useQuery directly where you have to pass in the client for every function call.
Let me know what you think :)