Fetching multiple queries at once with the Sanity client

24 replies
Last updated: Aug 18, 2022
Hey everyone. Is there a way to fetch multiple queries at once with the Sanity client? Let’s say I’ve this code:
  const firstQuery = `*[groq here][]{}`
  const secondQuery = `*[groq here][]{}`
  const thirdQuery = `*[groq here][]{}`

  const firstProp = await sanityClient.fetch(firstQuery)
  const secondProp = await sanityClient.fetch(secondQuery)
  const thirdProp = await sanityClient.fetch(thirdQuery)

  return {
    props: {
      firstProp,
      secondProp,
      thirdProp,
    },
  }
This seems wasteful somehow. Could I just fetch all three queries at the same time?
AI Update

Yes, absolutely! You can fetch all three queries at once using Promise.all(). This is much more efficient than awaiting each query sequentially because it runs them in parallel.

Here's how you'd rewrite your code:

const firstQuery = `*[groq here][]{}`;
const secondQuery = `*[groq here][]{}`;
const thirdQuery = `*[groq here][]{}`;

const [firstProp, secondProp, thirdProp] = await Promise.all([
  sanityClient.fetch(firstQuery),
  sanityClient.fetch(secondQuery),
  sanityClient.fetch(thirdQuery)
]);

return {
  props: {
    firstProp,
    secondProp,
    thirdProp,
  },
};

This way, all three queries are sent to Sanity at the same time, and your code waits for all of them to complete together. Instead of taking (time for query 1) + (time for query 2) + (time for query 3), it takes roughly the time of your slowest query.

The performance improvement can be significant, especially if you have multiple queries or slower network conditions. Each fetch() call returns a Promise, and Promise.all() waits for all of them to resolve, then returns an array of results in the same order you passed them in.

This pattern works great with any of Sanity's client methods - whether you're in getStaticProps, getServerSideProps, server components, or anywhere else you're fetching data from Sanity. The Sanity client's fetch() method is designed to work seamlessly with standard JavaScript promise patterns like this.

you make a query that looks like the following :
const allQueries =
{ firstQuery, secondQuery, thirdQuery }
and thenyou can fetch it with
sanityClient.fetch(allQueries)
and get the result will be an object with the result of each query in the correspondingly named field.
Awesome. I’ll give this a try. So this would return a single prop as an object, correct?
Yeah, it would return a single object, with the result of each query in the named field.You could define the object like this

const allQueries = { firstProp: firstQuery, secondProp: secondQuery, thirdProp: thirdQuery } 
const results = await sanityClient.fetch(allQueries }
return { props : results }
And that would be equivalent to your example-code.

The object you define your queries with is basically a javascript-object. You can name the fields anything you want, and Sanity will take the query in each field, and return a javascript object with the results of the query behind your chosen name in the object.
This is great. Excellent explanation! I’ll give this a try
So I’m getting a weird error:
ClientError: expected ']' following array body
So I’m getting a weird error:
ClientError: expected ']' following array body
The first query returns an array of objects (which is expected), while the other two just a single one.
Your query is invalid. 🙂
Hi
user F
. Thought about that, but the same query worked just fine using three separate fetches…
Show me?
Sure. This works:
  const firstQuery = `*[groq here][]{}`
  const secondQuery = `*[groq here][]{}`
  const thirdQuery = `*[groq here][]{}`
  
  const firstProp = await sanityClient.fetch(firstQuery)
  const secondProp = await sanityClient.fetch(secondQuery)
  const thirdProp = await sanityClient.fetch(thirdQuery)

  return {
    props: {
      firstProp,
      secondProp,
      thirdProp,
    }
  }
This does not:

const firstQuery = `*[groq here][]{}`
  const secondQuery = `*[groq here][]{}`
  const thirdQuery = `*[groq here][]{}`
 
  const allQueries = {
    firstProp: firstQuery,
    secondProp: secondQuery,
    thirdProp: thirdQuery,
  }

  const allProps = await sanityClient.fetch(allQueries)

  return {
    props: {
      allProps
    }
  }
Yes, because the fetch method doesn’t accept an object, it expects a string.
const { a, b, c } = await sanityClient.fetch(
  `{
    "a": *[…],
    "b": *[…],
    "c": *[…]
  }`
);

return {
  props: { a, b, c },
};
ahhhh! let’s try this
That was it! you’re a genius. I moved all the queries to a string as per your example and it worked.
Lovely. 😊
From your example, how would I pass a param to the query? This doesn’t seem to work:
const querya = `*[groq here][]{}`
const queryb = `*[groq here][]{}`
const queryc = `*[groq here][]{}`

const { a, b, c } = await sanityClient.fetch(
  `{
    "a": $querya,
    "b": $queryb,
    "c": $queryc
  }`, 
{
querya: querya,
queryb: queryb,
queryc: queryc
}
);

return {
  props: { a, b, c },
};
You seem to be mixing up dynamically constructing the query string with different variables, and passing parameters to your GROQ queries. The latter expect variables in certain places, you can’t pass a whole expression and expect it to work. 🙂
If you just want to construct your meta query from different variables, use interpolation or a template literal instead.
const query = `{
  "a": ${queryA},
  "b": ${queryB},
  "c": ${queryC}
}`
Yeah I guess I was. I was thinking about params and it was the wrong approach
However, if your queries do need params, you still can pass them as usual:
const queryA = `*[ _type == "post" && category == $category ]`
const queryB = `*[ _type == "author" ]`
const query = `{ "a": ${queryA}, "b": ${queryB} }`
const { a, b } = await client.fetch(query, { category: 'foobar' })

Here we have a meta query made of 2 sub-queries A and B. Sub-query A actually needs a category via the
$category
parameter. We pass that argument to the fetch as usual. 🙂
This is awesome, perfect for what I needed. Thanks
user F
! 🥇
Fab. 💚

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?