How to expand/resolve reference in Portable Text serializer mark?
Looking at your code, you're running into the classic issue where references in Portable Text annotations aren't automatically expanded - you just get the reference object with _ref and _type.
There are two main approaches to solve this:
1. Expand References in Your GROQ Query (Recommended)
The cleanest solution is to expand the references when you fetch your content. You'll need to use GROQ's dereferencing operator (->) to expand references within your markDefs array:
*[_type == "yourDocType"] {
...,
body[] {
...,
markDefs[] {
...,
_type == "link" => {
...,
"internal": internal->{
_id,
_type,
slug,
title
// Add whatever fields you need from the referenced document
}
}
}
}
}This way, when your serializer receives the mark object, the internal property will contain the full document data instead of just a reference stub.
2. Fetch References Client-Side
If you can't modify your query, you can fetch the referenced document in your serializer component using Sanity's client:
import { useEffect, useState } from 'react';
import { client } from './sanityClient'; // your configured client
const link = ({ children, mark }) => {
const [resolvedLink, setResolvedLink] = useState(null);
useEffect(() => {
if (mark.internal?._ref) {
client.fetch('*[_id == $id][0]', { id: mark.internal._ref })
.then(doc => setResolvedLink(doc));
}
}, [mark.internal?._ref]);
const linkData = mark.external
? { url: mark.external }
: resolvedLink;
return <Link link={linkData}>{children}</Link>;
};However, this approach can lead to performance issues with multiple references (lots of individual requests).
Best Practice
The first approach (expanding in your GROQ query) is strongly recommended because it:
- Fetches all data in one request
- Avoids loading states in your components
- Better performance overall
- Follows Sanity's guidance on working with references
The key insight from the Beginners guide to Portable Text is that Portable Text stores references in the markDefs array, and you need to explicitly tell GROQ to expand them using the -> operator. References aren't automatically expanded because that would be inefficient - you only expand what you actually need.
Show original thread8 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.