Best way to access Sanity CMS data in a Next.js app using React Context or fetch query in route layout file.
Using React Context is a solid approach for sharing your settings data across components in Next.js pages directory! This is actually a common pattern when migrating from Gatsby's useStaticQuery since the pages directory doesn't have a direct equivalent for component-level data fetching.
Here's what I'd recommend:
The Context Pattern (Your Instinct is Right!)
Fetch your settings data in _app.js and provide it via Context. This gives you similar ergonomics to what you had with useStaticQuery:
// pages/_app.js
import { createContext, useContext } from 'react';
import { client } from '../lib/sanity';
export const SettingsContext = createContext({});
export function useSettings() {
return useContext(SettingsContext);
}
function MyApp({ Component, pageProps, settings }) {
return (
<SettingsContext.Provider value={settings}>
<Component {...pageProps} />
</SettingsContext.Provider>
);
}
MyApp.getInitialProps = async () => {
const settings = await client.fetch(`*[_type == "settings"][0]`);
return { settings };
};
export default MyApp;Then in your header/footer components:
import { useSettings } from '../pages/_app';
export function Header() {
const { siteTitle, brandColors } = useSettings();
return <header>{siteTitle}</header>;
}Alternative: Fetch in Each Page
If you prefer keeping data fetching in getStaticProps, you can fetch settings alongside your page data and pass them to a Layout component as described in this approach to pulling global settings:
// pages/index.js
export async function getStaticProps() {
const [pageData, settings] = await Promise.all([
client.fetch(`*[_type == "page"][0]`),
client.fetch(`*[_type == "settings"][0]`)
]);
return {
props: { pageData, settings },
revalidate: 60 // Use ISR to keep settings fresh
};
}The Context approach is generally cleaner for truly global data like settings since you don't need to fetch and pass settings through every single page's getStaticProps.
Keeping Data Fresh
Since settings are fetched at build time, consider using Incremental Static Regeneration (ISR) with a revalidate value, or set up webhooks to trigger rebuilds when your settings change in Sanity Studio.
The React Context pattern you found is definitely a best practice for this use case in the pages directory! It's the closest equivalent to Gatsby's useStaticQuery for global data. Not a n00b question at all - this is a common migration challenge! ♥️
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.