Search code examples
reactjsgraphqlgatsbycontentful

Getting reference data from Graphql using Gatsby/Contentful


I'm struggling to get the data from the reference part of my Graphql. I got a Contentful content model that includes references as you can see in the query below.

Now, I got a simple page like this, where I query data from Contentful:

import React from "react"
import { graphql } from "gatsby"

const PageTemplate = ({
    data: {
        islands: {
            id,
            title,
            featuredActivities: { id, title },
        },
    },
}) => {


    return (
                                    <article key={id}>
                                        <div>
                                            <h3>{title}</h3>
                                        </div>
                                    </article>

                                    <article key={featuredActivities.id}>
                                        <div>
                                            <h3>{featuredActivities.title}</h3>
                                        </div>
                                    </article>
    )
}

export const query = graphql`
query GetSinglePage($slug: String) {
  islands: contentfulPage (slug: {eq: $slug}) {
        id
        title
        featuredActivities {
            id
            title
            category
            price
            image {
              fluid {
                ...GatsbyContentfulFluid
              }
            }
          }
      }
  }
`
export default PageTemplate

And now I want to get the data for this part of the query:

featuredActivities {
            id
            title
            category
            price
            image {
              fluid {
                ...GatsbyContentfulFluid
              }
            }
          }

I've tried this:

const PageTemplate = ({
    data: {
        islands: {
            featuredActivities: { id },
            featuredActivities: { title },
        },
    },

and added it like this into the :

<article key={featuredActivities.id}>
  <h3>{featuredActivities.title}</h3>
</article>

But it's not working, does someone knows what I'm doing wrong?

Thanks in advance

[![enter image description here][1]][1]


Solution

  • And now I want to get the data for this part of the query

    You can't destructure all items of the array like this:

    const PageTemplate = ({
        data: {
            islands: {
                featuredActivities: { id },
                featuredActivities: { title },
            },
        },
    

    Why? Because it's an array of objects and the structure ({}) doesn't match the type of the nested item. And, in case it was, and you will need to enter each specific position.

    You may need to:

    const PageTemplate = ({
        data: {
            islands: [{
                featuredActivities: { id },
                featuredActivities: { title },
            }],
        },
    

    Notice the wrapping square brackets ([]).

    However, as I said, it's not ideal since you need to print each specific position of the array of an unknown length. The best and optimal solution is to destructure until featuredActivities and loop through all elements:

    const PageTemplate = ({
        data: {
            islands: {
                id,
                title,
                featuredActivities,
            },
        },
    }) => {
    
    
        return <>
         {featuredActivities.map(({title, id})=>{
           return <div key={id}>{title}</div>
         })}
        </>
    }
    

    In that way, you can destructure inside the same loop in ({title, id}), since you are getting for each specific position (featuredActivity, the iterable variable), the title and the id (and so on for the rest of the needed fields).