
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeLooking 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:
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.
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).
The first approach (expanding in your GROQ query) is strongly recommended because it:
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.
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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store