Next.js: How to do client-side data fetching with grapql and headless CMS (graphCMS)

178 views Asked by At

I'm currently facing an issue with fetching data in a client-side component using Next.js app dir, and I'm hoping to get some assistance with resolving it.

I have a specific requirement where I need to fetch data with graphql from graphCMS within a client-side component in Next.js. However, I'm unsure of the best approach to accomplish this. I have attempted a few different methods, but none of them seem to be working as expected.

Here's a simplified version of my component code:

This graphql request is located in a different file (index.js)

export async function getAllPosts() {
  const query = gql`
    query Posts {
      articles {
        id
        title
        excerpt
      }
    }
  `;
  const result = await request(graphqlAPI, query);
  return result.articles;
};

From my Home component, I am trying to get the data from getAllPosta() as follow. But in the console it ends in an boring infinite loop.

'use client'
import { useEffect, useState } from "react";

export default Home(){
  const [data, setData] = useState([])

  useEffect(() => {
    getAllPosts().then((result) => {
      setData(result);
    });
  })

  return (
    data.map(post => {
      <div key={post.id}>
        <h1>{post.title}</h1>
        <p>{post.excerpt}</p>
      </div>
    })
  )
}

Thank you

1

There are 1 answers

0
alexortizl On

Assuming this simplified version of your code is close to the real implementation I would say that your problem is with useEffect. You don't have a dependency array so useEffect runs on every render, since it updates your component state with setData(result), it will trigger a render causing useEffect(...) to run again and hence an infinite loop. If you only need to fetch the data once you just need to add [] to the dependencies. Your code should be something like this:

'use client'
import { useEffect, useState } from "react";

export default function Home(){
  const [data, setData] = useState([])

  useEffect(() => {
    getAllPosts().then((result) => {
      setData(result);
    });
  }, []) // <-- note the '[]' here
 
  return (
    data.map(post => {
      <div key={post.id}>
        <h1>{post.title}</h1>
        <p>{post.excerpt}</p>
      </div>
    })
  )
}