Accessing referenced document data in Gatsby from Sanity reference field

66 replies
Last updated: Jun 14, 2020
Hello!
I’ve put more time than I’d like to admit into figuring this one out.
😶
I’ve built a
reference schema
that I can use within my
Block Type
that pulls 1 featured document into GatsbyJS.
I’m having trouble accessing the data of the document. I am capable of pulling the 
_ref
which is equal to the
id
of the post selected so I know I’m close. How do I get pull the data and into the data of the specific document?

Schema:

export default {
  
name: 'featuredPost',
  
title: 'Featured Post',
  
type: 'object',
  
fields: [
   
{
    
title: 'post',
    
name: 'post',
    
type: 'array',
    
of: [
     
{
      
type: 'reference',
      
to: [
       
{type: 'Doc Type 1'},
       
{type: 'Doc Type 2'},
      
]
     
}
    
]
   
},
  
]
 
}


GatsbyJS:
{postId._ref}
successfully shows id of document

function SingularFeaturedPost (_props_) {

const postId = _props_.featuredPost[0]

return (

<>

<h1>Featured Post: {postId}</h1>

<p>Post Title: {postId.title}</p>

</>

)

}


export default SingularFeaturedPost;

Thanks In Advance!
AI Update

I can see your issue! You're getting the _ref but not the actual referenced document data. This is a common challenge when working with Sanity references in Gatsby.

The key is that gatsby-source-sanity actually resolves references for you automatically in GraphQL queries, but you need to explicitly request the fields you want in your GraphQL query. The reference data won't be available in your component props unless you query for it.

Here's how to fix it:

In your GraphQL query (in your page or template file), you need to expand the reference like this:

query {
  # your query here
  sanityYourDocType {
    featuredPost {
      post {
        # These are the fields from the referenced document
        _id
        title
        slug {
          current
        }
        # add any other fields you need from the referenced doc
      }
    }
  }
}

The gatsby-source-sanity plugin automatically resolves references when you query through GraphQL - you just need to specify which fields you want from the referenced document.

Alternative approach using _rawPost:

If you need deeper reference resolution or are working with Portable Text that contains references, you can use the special _raw fields that gatsby-source-sanity generates:

query {
  sanityYourDocType {
    _rawFeaturedPost(resolveReferences: { maxDepth: 5 })
  }
}

The _raw fields give you the complete raw data from Sanity with references resolved to the depth you specify. This is particularly useful for complex nested references.

Why you're only seeing _ref:

When you don't explicitly query for the referenced document's fields in GraphQL, Gatsby only gives you the reference stub (the _ref field). The actual document data exists in Gatsby's data layer, but you need to tell GraphQL to fetch and join it.

Once you update your GraphQL query to include the fields you need, your component code should work as-is - postId.title will be available because the reference will be fully resolved in your props.

Show original thread
66 replies
sounds like you need to look for the
_raw
content of your blockType
can you share a GiQL of your query?
user N
Thanks for the response. Here’s some more information:
I’m pulling the information through the serializer of my blockContent.

Through the following GiQL query I can see the information after reference:


query MyQuery {

sanityPage {

title

_rawBlockContent(resolveReferences: {maxDepth: 10})

}

}
ok, so what's inside the
_rawBlockContent
? what are you serializing it to?
Inside the _rawBlock is:

{

"data": {

"sanityPage": {

"title": "Title",

"_rawBlockContent": [

{

"_key": "1d4f1c4d53c6",

"_type": "block",

"children": [

{

"_key": "1d4f1c4d53c60",

"_type": "span",

"marks": [

"strong"

],

"text": "Text Here"

},

{

"_key": "1d4f1c4d53c61",

"_type": "span",

"marks": [],

"text": "text here"

}

],

"markDefs": [],

"style": "normal"

},

{

"_key": "90e78fe9aa66",

"_type": "singularFeaturedPost",

"featuredPost": [

{

"_id": "06df3cdd-2aae-4b5d-bff7-2fbe7a77b65c",

"_type": "business",

"_createdAt": "2020-06-01T16:22:11Z",

"_rev": "QyhMGiXtoE71bfRC5kaum9",

"_updatedAt": "2020-06-01T21:11:52Z",

"excerpt": "Excerpt will go here. ",

"featuredContent": [

"publishedAt": "2020-04-16T05:00:00.000Z",

"slug": {

"_type": "slug",

"current": "slug-here"

},

"title": "title-here",

"id": "a6dea004-b4a8-54f9-a834-bd616ce733ec",

"parent": null,

"children": [],

"internal": {

"type": "SanityBusiness",

"contentDigest": "a81065371c02714e51e7ac1f338a10d7",

"counter": 73,

"owner": "gatsby-source-sanity"

}

}

]

},

{

"_key": "84dc53750d15",

"_type": "block",

"children": [

{

"_key": "84dc53750d150",

"_type": "span",

"marks": [],

"text": "Content:"

}

],

"markDefs": [],

"style": "normal"

},

{

"_key": "4578b407565d",

"_type": "recentPostFeed",

"contentType": "music",

"featureFirstPost": false,

"postCount": 6

},

{

"_key": "4c7e082d5de1",

"_type": "block",

"children": [

{

"_key": "4c7e082d5de10",

"_type": "span",

"marks": [],

"text": "Business:"

}

],

"markDefs": [],

"style": "normal"

},

{

"_key": "744429e46d6a",

"_type": "recentPostFeed",

"contentType": "business",

"featureFirstPost": false,

"postCount": 3

}

]

}

}

}
ok, so isn't that your referenced document right there? titled
title-here
??
Yes. Getting to it is where I’m perpetually stuck.
gotcha gotcha
props.featuredPost[0]._ref shows the ID of the doc I need information from. Getting into that doc through : props.featuredPost… is where I’m hung up.
ok, lets take it slow here (since i'm trying to follow code i can't test)... what do you get when you log out
props
?
or perhaps
props.featuredPost.title
I know props.featuredPost.title renders undefined
I’m throwing props in now.
mmm
Props Straight Up:
1. _{_key: “90e78fe9aa66”,
type: “singularFeaturedPost”, featuredPost: Array(1)}2. featuredPost: [{…}]
3. _key: “90e78fe9aa66”
4. _type: “singularFeaturedPost”
5. __proto__: Object

might also depend on where you're logging for
props
... before serializer and after
where are you logging that?
within my component. Right before return
which component? the Post component, the component that serializer sends the data to?
Within the singularFeaturedPost that is referenced in the serializer.
The one that sends the data to.
got it
so AFTER the serializer
Yes. Thanks for the patience.
which means you're not sending the right data to your component
so we need to go back a component and see what data you're sending through to it
Little more info coming…
ok
i've got to jump to a call in a few minutes but happy to continue to help till then, adn then again after
just as a heads up if i just stop responding for 30 min
I built a recent post schema type that shows 5 recent posts from any doc type selected. It works great.
With that component I’m using a staticQuery within the component that is serialized.
Since this is referencing one item with a defined id I’m not using a staticQuery. Is that correct?
Thanks for the heads up on the call.
yeah, you should be fine with this approach
i have several questions... did you query for the
_raw
somewhere? are you passing the data from that GQL query in total, all the way down to your component (through serializer)
that's what i'm trying to sleuth out right now
Here is my full seralizer.js in regards to this scenario:

import BaseBlockContent from '@sanity/block-content-to-react'

import React from 'react'

import SingularFeaturedPost from './SingularFeaturedPost'


const serializers = {

types: {

singularFeaturedPost (_props_) {

return <SingularFeaturedPost {...props.node} />

},


}

}


const BlockContent = ({ _blocks_ }) => <BaseBlockContent _blocks_={_blocks_} _serializers_={serializers} />


export default BlockContent
great... i'll review in a few
i'll be back 😉
Great! Thanks again.
Here is the page.js in full:

import React from 'react'

import { graphql } from 'gatsby'

import SiteLayout from 'c32-gatsby-theme-core/src/components/layout'

import { SEO, Layout } from "c32-gatsby-theme-core"

import GraphQLErrorList from 'c32-gatsby-theme-core/src/components/graphql-error-lists'

import Container from 'c32-gatsby-theme-core/src/components/container'

import BlockContent from '../../src/components/block-content'

`export const query = graphql``

query HomePageQuery {

page: sanityPage(_id_: {eq: "e07ca5b6-bcc6-5d90-8489-39702cd11394"}) {

title

_rawBlockContent

}

}
```


const Homepage = _props_ => {

const { data, errors } = _props_


if (errors) {

return (

<Layout>

<GraphQLErrorList _errors_={errors} />

</Layout>

)

}

const page = data && data.page

if (!page) {

throw new Error(

'Missing "Home" page data. Open the studio at <http://localhost:3333> and add "Home" page data and restart the development server.'

)

}


return (

<SiteLayout>

<Container>

<BlockContent _blocks_={ page._rawBlockContent || [] } />

</Container>

</SiteLayout>

)

}


export default Homepage
I’ve got a client meeting in 30min. I’ll be available until then and after that.
ok, so ... this looks good... i'm assuming if you log
page._rawBlockContent
you get what you're looking for on Homepage
For all my pages I do. I get the sanity block content.
And all my schema types I’ve made work as well up until this one.
so when are you using the
block-content-to-react
component? and when do you serialize?
in example, here's how one of mine is setup

import React from 'react'
import BlockContent from '@sanity/block-content-to-react'
import serializers from './Serializers'

const PortableText = ({ className, blocks }) => (
  <BlockContent className={className} blocks={blocks} serializers={serializers} />
)

export default PortableText
looking at your
<BlockContent>
you're not using the serializer at this step (which is where i typically have mine)
also not seeing the import of that block to react component
Both the block content and sericalizer are within the BlockContent
serializers={serializers}
got it
Oh nice catch…
I just noticed that the serializer isn’t at that step. One moment I’ll review.
just for reference to the flow i'm using.. its something like PageTemplate &gt; PortableText component &gt; Block-to-React via serializer &gt; final component
I’m going to move my serializer down to the initial level and try your order. It’ll take a while with work requirements. Ideally I’ll report back that it was a success.
I see your in the MPLS area as well. Small world.
🙌
sounds good... let me know when you get there... i'm happy to share files for any of this if its helpful
where in MPLS are you?
AV, You?
SLP
was just thinking abotu this more.... i think you need the serializer at the same point as the block-to-react component, as i think it needs the serializer
i think serializer and block-to-react go hand in hand
Gave restructuring it a shot so it looked identical to your approach. I had same inability to get information from within the referenced document types.
If I log
const featuredPost = _props_.featuredPost[0]._type
it returns
reference
. This seems one level up. I would assume the array is contained within the type
reference
rather than
reference
being in the first spot of the array.
I think this is the foundation of my user error. I SUPER appreciate the help today.
user M
Let me know if you need any additional information. Thanks for looking into this!
interesting... i'll be interested to hear what
user M
has to say
user M
responded with the solution:
Your 
/pages/index.js
 file, where you query 
_rawBlockContent
, try querying it with 
resolveReferences
. For example:
export const query = graphql`
  query HomePageQuery {
    page: sanityPage(id: {eq: "e07ca5b6-bcc6-5d90-8489-39702cd11394"}) {
      title
      _rawBlockContent(resolveReferences: {maxDepth: 5})
    }
  }
`
Good to know the scope starts shallow and can show more depth by request. Makes sense.
Thanks for re-posting the solution here, Ryan! And thanks for all the troubleshooting you both did on the way, really appreciated. cc: Bryce 🙂

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?