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:
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.
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 }[] }