Reference fields not resolving in Portable Text serializer components

14 replies
Last updated: Jan 28, 2026
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.

Show original thread
14 replies

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?