Using GROQ queries in Next.js components and the limitations of fetching data on the client-side.
I can see the issue! You're trying to use getStaticProps inside a component file, but getStaticProps only works in page files in Next.js (files inside the pages/ directory). That's why it works on pages but returns an empty array in your component.
Here are your solutions depending on your Next.js version:
For Next.js App Router (13+)
Convert your component to a Server Component and fetch data directly inside it:
import React from 'react';
import groq from 'groq';
import { createClient } from 'next-sanity';
import { Heading } from '../elements';
// Create your Sanity client
const client = createClient({
projectId: 'your-project-id',
dataset: 'production',
apiVersion: '2024-01-01',
useCdn: true,
});
const ReviewBlock = async ({ title }) => {
// Fetch directly in the component
const products = await client.fetch(groq`
*[_type == "product" && isFeatured && !(_id in path('drafts.**'))]
{"id": _id, ...} | order(publishedAt desc)
`);
console.log(products, 'products');
return (
<section className="section is-medium">
<div className="container">
{title && (
<Heading centered className="has-text-black mb-6">
{title}
</Heading>
)}
</div>
</section>
);
};
export default ReviewBlock;This works because Server Components in the App Router can be async and fetch data directly.
For Next.js Pages Router (12 and below)
You have two options:
Option 1: Fetch in the page and pass as props
// pages/your-page.js
export async function getStaticProps() {
const products = await sanity.fetch(groq`
*[_type == "product" && isFeatured && !(_id in path('drafts.**'))]
{"id": _id, ...} | order(publishedAt desc)
`);
return {
props: { products }
};
}
export default function YourPage({ products }) {
return <ReviewBlock title="Reviews" products={products} />;
}
// components/ReviewBlock.js
const ReviewBlock = ({ title, products = [] }) => {
// Just use the products prop
console.log(products, 'products');
return (/* your JSX */);
};Option 2: Fetch client-side with SWR or useEffect
import useSWR from 'swr';
import groq from 'groq';
import sanity from '../../utils/sanity';
const ReviewBlock = ({ title }) => {
const { data: products = [] } = useSWR(
groq`*[_type == "product" && isFeatured && !(_id in path('drafts.**'))]
{"id": _id, ...} | order(publishedAt desc)`,
(query) => sanity.fetch(query)
);
console.log(products, 'products');
return (/* your JSX */);
};For shared components (Header/Footer)
For layout components that need data:
- App Router: Create them as async Server Components (like the first example above)
- Pages Router: Fetch data in your page's
getStaticPropsand pass it down, or use client-side fetching with SWR/React Query
The key takeaway: getStaticProps and getServerSideProps are page-level only in the Pages Router. For components, you either need to pass data down as props, use Server Components (App Router), or fetch client-side.
Check out the next-sanity package documentation for more patterns on integrating Sanity with Next.js!
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.