Skip to main content

FAQs

How do I pass parameters to my groq query?

To pass params to your groq query, you can create a runQuery function that wraps makeSafeQueryRunner and passes the params as an object to the client object.

const client = sanityClient({
/* ... */
});

// 👇 add a params argument
const runQuery = makeSafeQueryRunner((
query: string,
params: Record<string, number | string> = {}
) => client.fetch(query, params));

const query = q("*")
.filter("_type == 'pokemon'")
.order("name $direction") // 👈 use GROQ parameters
.grab({
name: q.string(),
});

// 👇 and pass parameter values to your query runner.
runQuery(query, { direction: 'asc' })

How should I extract out portions of my query for reuse?

There are a few ways to extract out portions of your groqd queries for reuse. We'll cover two of the more common ways here.

Extract out a "selection"

The .grab/.grab$ methods take a Selection as an argument. You can extract that Selection value out into a variable and reuse it. Here's an example.

Suppose you're querying on an "Author" type and want to grab some author information.

import { q } from "groqd";

q("*")
.filterByType("author")
.grab$(/* the following is a `Selection` */ {
name: q.string(),
age: q.number(),
});

You can extract the { name, age } selection into its own variable and use that across multiple locations:

import { q, type Selection, type TypeFromSelection } from "groqd";

// create an author selection satisfying `Selection` type.
export const authorSelection = {
name: q.string(),
age: q.number(),
} satisfies Selection;

// optionally export out the type, { name: string; age: number }
export type AuthorResult = TypeFromSelection<typeof authorSelection>;

// and use the selection
q("*")
.filterByType("author")
.grab$(authorSelection);

Extract out a "sub query"

You might also find yourself writing "sub queries" like the following:

import { q } from "groqd";

q("*")
.filterByType("author")
.grab$({
name: q.string(),
// 👇 a `posts` "sub query" here.
posts: q("*")
.filter("_type == 'posts' && references(^._id)")
.grab$({
title: q.string(),
body: q.string(),
}),
})

In the case of the posts "sub query", you could also abstract that entire bit out into a variable for reuse, if needed:

import { q, type InferType } from "groqd";

// extract out sub query
export const authorPostsQuery = q("*")
.filter("_type == 'posts' && references(^._id)")
.grab$({
title: q.string(),
body: q.string(),
});

// optionally export the type, { title: string; body: string; }[]
export type AuthorPosts = InferType<typeof authorPostsQuery>;

// and use the sub query variable
q("*")
.filterByType("author")
.grab$({
name: q.string(),
posts: authorPostsQuery
})

How might I write a UI component for a groqd query/selection?

If you have a UI component that you want to use to render the result of a groqd query/selection, you can use the two methods from above to extract out selections/queries and link them up to a UI component. Here's an example using React.

One approach is to define a Selection and use the type for your React component's prop type:

AuthorDisplay.tsx
import { q, type Selection, type TypeFromSelection } from "groqd";

export const authorSelection = {
name: q.string(),
age: q.number(),
} satisfies Selection;

type AuthorDisplayProps = TypeFromSelection<typeof authorSelection>;

export function AuthorDisplay({ name, age }: AuthorDisplayProps) {
return (
<div>
<h3>{name}</h3>
<p>{age} years old</p>
</div>
);
}

We'll make sure to export the component itself and the selection, so we can use them elsewhere.

Then from some sort of "parent" component, we can use the selection in a query, and render the component accordingly.

AuthorList.tsx
import { q } from "groqd";
import { runQuery } from "~/runQuery";
import { authorSelection, AuthorDisplay } from "./AuthorDisplay";

// Craft our query
async function getAuthors() {
return runQuery(
q("*")
.filterByType("author")
.grab$(authorSelection)
);
}

export async function AuthorList() {
const authors = await getAuthors();

return (
<div>
{authors.map(author => <AuthorDisplay key={author.name} {...author} />)}
</div>
)
}

Can groqd handle groq's coalesce operator?

Yes! You can write a coalesce expression just as if it were a field expression. Here's an example with groqd:

q("*")
.filter("_type == 'pokemon'")
.grab({
name: q.string(),
// using `coalesce` in a `grab` call
strength: ["coalesce(strength, base.Attack, 0)", q.number()],
});

Can I perform multiple queries in one request?

Yes! To make multiple queries, you can leave the initial query empty and add a .grab with multiple queries as values on that .grab, as shown below.

import { q } from "groqd";

q("").grab({
posts: q("*").filter("_type == 'post'").grab({ name: q.string() }),
faqs: q("*").filter("_type == 'faq'").grab({ content: q.string() }),
});
// { posts: { name: string }[]; faqs: { content: string }[] }