Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

Using GROQ queries in Next.js components and the limitations of fetching data on the client-side.

11 replies
Last updated: Dec 18, 2021
help: I use the GROQ query in the next js components, not pages. it's not fetching data. showing empty array. But on the other hand, if add this query on the page its works fine. So the question is how I use this query in the header, footer, others.              So please someone help me? How I write query I next component. So my code is..  

import React from 'react';
import groq from 'groq';
import sanity from '../../utils/sanity';

import { Heading } from '../elements';

const ReviewBlock = ({ title, products = [] }) => {
  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 async function getStaticProps() {
  return {
    props: {
      products: await sanity.fetch(groq`
          *[_type == "product" && isFeatured && !(_id in path('drafts.**'))] {"id": _id, ...}|order(publishedAt desc)
        `),
    },
  };
}
export default ReviewBlock;
Dec 13, 2021, 9:54 AM
I think getStaticProps etc only work on pages iirc.
You could maybe try using the
useEffect
hook to fetch the data in the component instead?
Dec 13, 2021, 10:49 AM
Just looking through the Nextjs documentation, my above message might not be correct, example https://nextjs.org/docs/basic-features/data-fetching#example
Dec 13, 2021, 10:53 AM
user B
you are correct, you can only use getStaticProps in a page not a component
Dec 13, 2021, 12:35 PM
You can’t fetch data at a component level. What you’ll need to do is either extract your global data at build time with something like next-plugin-preval or pass the it as props in your layout component.
Dec 13, 2021, 1:45 PM
user P
Ah ok, that was my first thought but started to second guess myself 😄
Dec 13, 2021, 1:46 PM
thanks,
user B
it's working now.
Dec 13, 2021, 6:08 PM
 const [review, setReview] = useState(null);

  useEffect(() => {
    sanity
      .fetch(
        groq`
        *[_type == "product" && !(_id in path('drafts.**'))] {"id": _id, ...}
        `,
      )
      .then((data) => setReview(data));
  }, []);
  console.log(review);
Bingo
Dec 13, 2021, 6:08 PM
user B
can you please explain to me? is it good or bad? Fetch data direct in components. Nextjs now allow this in their props( getstaticprops , getInitial , etc).. Give me a pro tip. if it wrong method then I remove it from my code and find the better one.
Dec 13, 2021, 6:12 PM
Non-page component cannot fetch their own data on the server side. So you need to fetch it in the page it is in and pass that data down as props. If the data is used widely throughout the site, I'd fetch it in
_app
and make it available through context.
The workaround you are using above is fetching data on the client side, at run-time. Now this is not entirely bad but might affect your SEO, as that component's rendered content won't be available when the bot is crawling your site. And server rendered markup (especially when used with static optimization) will most of the time result in faster first load.
Dec 14, 2021, 2:53 AM
user M
Thank you for giving me this information. Thanks
Dec 14, 2021, 8:10 AM
Not to mention each page load will result in an api request, counting towards the limits.
Dec 18, 2021, 10:19 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?