useStaticQuery is a React Hook that comes with Gatsby that allows us to query data inside a component, and use that component anywhere. The most typical use-case for this is something like a header menu, or set of footer links, but can also be used for things like cross-site product filtering and other cool stuff, where you don't want to be restricted to the boundaries of a template or page query.

Let's make a header menu

To understand how this works, we're going to use useStaticQuery to power a menu in a Gatsby/Strapi build.

The key limitation of useStaticQuery

Many new Gatsby developers think useStaticQuery will solve all their problems when they first discover it. They think Wow, now I can get any data, anywhere, at any time!

Unfortunately the reality is not so simple.

With useStaticQuery, you face the same limitations of querying per page or per template - you can't use string interpolation to query things when props change. This is due to the underlying nature of Gatsby. Although during the build process, it'll download all of your data - it throws away what it doesn't need as soon as that's done, and thus cannot perform any sort of dynamic GraphQL queries on the pages and components themselves.

In technical terms, what is actually happening under the hood when you run a query or use the useStaticQuery hook is this:

  1. Gatsby uses a custom Babel parser to find your GraphQL queries in both your pages and components and extracts them.
  2. It runs the queries against the data source it has downloaded, and returns the response as JSON.
  3. It creates a page-data.json file for all of these JSON responses, which is then saved to your public folder. It replaces the GraphQL query inside useStaticQuery with the ID of the page-data.json file (so it knows where to grab it from later when your site is live).
  4. Whenever a query is run on the client, it grabs this page-data.json file, parses it, and feeds it into your components.

Don't over-do it

With useStaticQuery, your elements are most likely globally-visible things like headers and footers. As such, the more data you query with useStaticQuery, the bigger the create JSON files are likely to be, and the larger requests the web browser is going to have to make - something that is highly visible on slow internet connections.

Therefore - please do not run big queries inside useStaticQuery. Because there's probably a better work around using page and template level queries.