Troubleshooting reference fields in a Next.js Landing page template

10 replies
Last updated: May 2, 2020
I'm working off the Next.js Landing page template. I've created a new document called Features. I want to be able to reference the features and insert them into a Page. I have the studio set up correctly so I can add the Features within the page. When I have two features in there, I can get 2 empty divs to show up on my front end so it seems like it's finding the referenced documents, but I'm missing data for the titles etc.
I'm returning

{features && (
          <ul>
            Posted in
            {features.map(feature => <li key={feature}>{feature.title}{feature.key}</li>)}
          </ul>        )}
But I think I can't get the groq query right. For that I have:


if (slug && slug === '/') {
      return client
        .fetch(
          groq`
        *[_id == "global-config"][0]{
          frontpage -> {...,content[] {...,},
          features
        }
      }
      `
        )
        .then(res => ({...res.frontpage, slug}))
    }
I can't seem to pass the title or any of the features fields to it.
AI Update

The issue is that your GROQ query isn't properly dereferencing the features array. When you have references in Sanity, you need to explicitly expand them using the -> operator and specify which fields you want to retrieve.

Your current query has features without any projection, which returns just the reference objects (containing _ref, _type, _key) rather than the actual feature document data. That's why you're seeing empty divs - the array exists but doesn't contain the field data you need.

Here's the corrected query:

*[_id == "global-config"][0]{
  frontpage -> {
    ...,
    content[] {...},
    features[] -> {
      _id,
      title,
      _key,
      // add any other fields from your Features document
    }
  }
}

The key changes:

  1. features[] -> - The [] tells GROQ this is an array, and -> dereferences each reference in the array
  2. Projection after -> - You need to specify which fields to pull from the referenced Feature documents

If your Features documents have more fields (like description, icon, etc.), add those to the projection as well.

In your React code, you should then be able to access the data like this:

{features && (
  <ul>
    {features.map(feature => (
      <li key={feature._id}>
        {feature.title}
      </li>
    ))}
  </ul>
)}

Note: I changed the key from feature (the whole object) to feature._id since React keys should be strings/numbers, not objects. The _key field would also work if your reference array items have unique keys.

The projections documentation explains how to use the -> operator to follow references and shape the returned data. This is essential when working with Sanity's reference fields to ensure you're fetching the actual document content rather than just the reference metadata.

have you tried console logging the features variable to make sure there is something to map over?
Hi Anders, thanks for the response, i'm having trouble finding the right place to put the console log, would you mind directing me?
If I add an extra document reference in the page, I get an extra empty item on the page. So it's mapping over something
help really appreciated I've been stuck on this for 2 days. I was able to make some progress with the blog post you linked me to the other day, but i think one last piece of the puzzle is missing šŸ™‚
I think about line 73 in your github before you set the openGraphImages var inside your render console.log(features) will let you know, my guess is it's an empty array I'll look at your code to see if I see anything I can tell. I haven't used groq just graphql, but i'll take a look.
Thanks
user S
! I do see this. So seems it's not empty?
Try
if (slug && slug === '/') {
      return client
        .fetch(
          groq`
        *[_id == "global-config"][0]{
          frontpage -> {...,content[] {...,},
          features[]->
        }
      }
      `
        )
        .then(res => ({...res.frontpage, slug}))
    }
Since
features
is an array, you have to traverse it
[]
, and since this is an array of reference objects, you can add
->
Ā to join the documents. Since youā€˜re not using all the fields here, Iā€˜d perhaps project only those you need as well:
features[]->{_id, title)
Then you can

{features.map(feature => <li key={feature._id}>{feature.title}</li>)}

Try
if (slug && slug === '/') {
      return client
        .fetch(
          groq`
        *[_id == "global-config"][0]{
          frontpage -> {...,content[] {...,},
          features[]->
        }
      }
      `
        )
        .then(res => ({...res.frontpage, slug}))
    }
Since
features
is an array, you have to traverse it
[]
, and since this is an array of reference objects, you can add
->
Ā to join the documents. Since youā€˜re not using all the fields here, Iā€˜d perhaps project only those you need as well:
features[]->{_id, title)
Then you can

{features.map(feature => <li key={feature._id}>{feature.title}</li>)}

Glad to hear! Don’t hesitate to let us know before it has gone 2 days if you're stuck šŸ™‚

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.

Was this answer helpful?