Issue with accessing reference types in serializer components

14 replies
Last updated: Aug 14, 2021
Is there some kind of rule with references inside serializer components? I’m trying to implement a page builder inside portable text and defining the structure of each section inside the serializer, it works great until I try to map over an object and display data that’s a reference type. It returns it as undefined.
JSON:

"gridItems": [

{

"_key": "e9a8137c2bd0",

"_type": "bestExchangesGridByCountry",

"country": "Australia",

"flag": {

"_type": "image",

"asset": {

"_ref": "image-feb24aaa0dfa7ce041c72f80f051588f650e6133-1280x640-svg",

"_type": "reference"

}

},

"gridItems": [

{

"_key": "a27f884f71c7",

"_type": "cardBestExchanges",

"category": "Overall",

"exchangeRef": {

"_ref": "115562b1-ebff-465a-9f40-720119eb472a",

"_type": "reference"

},

"ourPick": true

},

{

"_key": "0f8fe217cefe",

"_type": "cardBestExchanges",

"category": "Security",

"exchangeRef": {

"_ref": "26b859eb-4365-4954-9d73-b5a65e39ca57",

"_type": "reference"

}

},

{

"_key": "86b7c678da10",

"_type": "cardBestExchanges",

"category": "Mobile App",

"exchangeRef": {

"_ref": "3de1e3e2-336b-4eee-a662-81a4de537318",

"_type": "reference"

}

},

{

"_key": "71b4f35bc1f6",

"_type": "cardBestExchanges",

"category": "Beginners",

"exchangeRef": {

"_ref": "7e32329c-be19-4ef3-ba75-0f18ad6b566c",

"_type": "reference"

},

"sponsored": true

}

]

My code:

gridBestExchanges: (_props_) => {

return (

<>

<div>Section body: {_props_.node.body}</div>

<div>Disclaimer: {_props_.node.disclaimer && <BlockContent _data_={_props_.node.disclaimer} />}</div>

<div>Exchange Cards: {_props_.node.gridItems.map((_node_) => (

<div _key_={_node_._key}>

{_node_.gridItems.map((_exchangeRef_) => (

<div _key_={_exchangeRef_._key}>{_exchangeRef_.name}</div>

))}

</div>

))}</div>

</>

)

},
AI Update

The issue you're experiencing is a common one when working with references in Sanity queries. When you fetch data using Portable Text serializers, references are not automatically expanded - they come through as reference objects with just _ref and _type fields.

The Problem

In your serializer, you're trying to access exchangeRef.name, but exchangeRef only contains:

{
  "_ref": "115562b1-ebff-465a-9f40-720119eb472a",
  "_type": "reference"
}

This means exchangeRef.name is undefined because the reference hasn't been dereferenced.

The Solution

You need to dereference the references in your GROQ query before the data reaches your serializer. Use the -> operator in your query:

*[_type == 'yourDocumentType'] {
  ...,
  content[] {
    ...,
    _type == 'gridBestExchanges' => {
      ...,
      gridItems[] {
        ...,
        _type == 'bestExchangesGridByCountry' => {
          ...,
          gridItems[] {
            ...,
            exchangeRef-> {
              _id,
              name,
              // other fields you need
            }
          }
        }
      }
    }
  }
}

The key part is exchangeRef-> which tells GROQ to follow the reference and expand it with the actual document data.

Alternative: Dereferencing Arrays of References

If you're working with an array of references (which appears to be your case with the nested gridItems), you need to use the array dereferencing syntax:

gridItems[] {
  ...,
  exchangeRef-> {
    _id,
    name,
    // other fields
  }
}

Important Note

As mentioned in the Sanity documentation on expanding references, when working with arrays of references, you must use the square brackets with the dereference operator: array[]-> not just array->. The brackets are mandatory to traverse the array and dereference each item.

The documentation specifically warns: "It would be easy to forget the square brackets when expanding an array of references (i.e., querying producers-> instead of producers[]->, with the former returning a single null value)."

After updating your query to properly dereference the references, your serializer code should work as expected because exchangeRef will contain the full document data including the name field you're trying to access.

I’ve tried passing it to my card comp as an entire object and by passing each individual field with no luck. It works with the page builder we’ve implemented as an array in the schema itself (outside the portable text editor) but for some reason isn’t working within the editor.
Have you specified a serializer for these custom cards?
Yep the above is basically just a crude version of it to get the data pulled in properly
Yep the above is basically just a crude version of it to get the data pulled in properly
Basically the problem is I’m not able to access the reference types from the serializer under ‘types’
They all come back us ‘undefined’ while everything else (that’s not a reference) works fine
Yep the above is basically just a crude version of it to get the data pulled in properly
It seems the reference object itself is there, but only the _ref value accessible it seems
Ah, ok then! The issue is that your references need to be resolved in order to get their values, otherwise you just get the _ref property. More info on how to do that here: https://www.sanity.io/docs/how-queries-work#8ca3cefc3a31
Ahhh that makes sense. Is there a resource for GraphQL?
…. Oh my god.
Rachael disregard me. I just. spent 5 (paid, on the clock) hours trying to figure out how to do this and all I had to do was add (_resolveReferences_: {maxDepth: 10}) to the _rawBody field in my query.
Thank you so much for helping me solve this
Hahaha, we’ve all been there, my friend! Glad you got it sorted out!

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?