The preview system provides utilities for rendering document previews and subscribing to preview data throughout the Studio.
DocumentPreviewStore
The document preview store manages subscriptions to document data for preview purposes. Documents observed by this store receive real-time updates but don’t support optimistic updates.
import {useDocumentPreviewStore} from 'sanity'
function MyComponent() {
const previewStore = useDocumentPreviewStore()
// Use preview store methods
}
observeForPreview
Observe a document’s preview data:
import {useDocumentPreviewStore} from 'sanity'
import {useEffect, useState} from 'react'
function DocumentPreview({documentId, schemaType}: Props) {
const previewStore = useDocumentPreviewStore()
const [preview, setPreview] = useState(null)
useEffect(() => {
const subscription = previewStore
.observeForPreview({_id: documentId}, schemaType)
.subscribe(setPreview)
return () => subscription.unsubscribe()
}, [documentId, schemaType, previewStore])
return <div>{preview?.title}</div>
}
Document or reference to preview
Schema type or type object
Preview optionsOptions for the preview preparation
Perspective stack for queries
observable
Observable<PreparedSnapshot>
Observable that emits prepared preview snapshotsPrepared preview dataPreview media (image, icon, etc.)
observePaths
Observe specific paths in a document:
previewStore.observePaths(
{_id: 'article-123'},
['title', 'slug.current', 'author.name']
)
Array of paths to observe (e.g., ['title', 'author.name'])
Observable that emits the document with requested paths
Preview Components
SanityDefaultPreview
Default preview component for documents:
import {SanityDefaultPreview} from 'sanity'
function DocumentItem({document, schemaType}: Props) {
return (
<SanityDefaultPreview
value={document}
schemaType={schemaType}
layout="default"
/>
)
}
layout
'default' | 'card' | 'media' | 'detail'
Preview layout style. Default: 'default'
Status indicator to display
Preview
Generic preview component:
import {Preview} from 'sanity'
function CustomPreview({documentId, schemaType}: Props) {
return (
<Preview
value={{_id: documentId}}
schemaType={schemaType}
layout="card"
/>
)
}
Value to preview (document, reference, or value with preview config)
layout
'default' | 'card' | 'media' | 'detail'
Layout style
PreviewLoader
Lazy-loading preview component:
import {PreviewLoader} from 'sanity'
function LazyPreview({documentId, schemaType}: Props) {
return (
<PreviewLoader
value={{_id: documentId}}
schemaType={schemaType}
>
{(preview) => (
<div>
<h3>{preview.title}</h3>
<p>{preview.subtitle}</p>
</div>
)}
</PreviewLoader>
)
}
Render function that receives prepared preview
Preview Utilities
getPreviewPaths
Extract preview paths from schema type:
import {getPreviewPaths} from 'sanity'
const paths = getPreviewPaths(schemaType)
// Returns: ['title', 'subtitle', 'media']
Schema type to extract paths from
Array of field paths used in preview
prepareForPreview
Prepare a value for preview:
import {prepareForPreview} from 'sanity'
const prepared = prepareForPreview(
document,
schemaType,
{selection: ['title', 'author']}
)
Prepared preview data with title, subtitle, description, and media
getPreviewValueWithFallback
Get preview value with fallback:
import {getPreviewValueWithFallback} from 'sanity'
const preview = getPreviewValueWithFallback({
value: document,
schemaType,
})
Preview with fallback values for missing fields
useValuePreview
Hook to observe preview data:
import {useValuePreview} from 'sanity'
function DocumentCard({document, schemaType}: Props) {
const {value, isLoading} = useValuePreview({
value: document,
schemaType,
})
if (isLoading) return <div>Loading...</div>
return (
<div>
<h3>{value.title}</h3>
<p>{value.subtitle}</p>
</div>
)
}
Preview resultWhether the preview is loading
Error if preview failed to load
Example: Custom Preview List
import {useValuePreview, useClient} from 'sanity'
import {Card, Stack, Text} from '@sanity/ui'
import {useEffect, useState} from 'react'
function DocumentList({schemaType}: {schemaType: string}) {
const client = useClient({apiVersion: '2024-01-01'})
const [documents, setDocuments] = useState([])
useEffect(() => {
client
.fetch(`*[_type == $type][0...10]`, {type: schemaType})
.then(setDocuments)
}, [client, schemaType])
return (
<Stack space={2}>
{documents.map(doc => (
<DocumentPreviewCard
key={doc._id}
document={doc}
schemaType={schemaType}
/>
))}
</Stack>
)
}
function DocumentPreviewCard({document, schemaType}: Props) {
const schema = useSchema()
const type = schema.get(schemaType)
const {value, isLoading} = useValuePreview({value: document, schemaType: type})
if (isLoading) return <Card padding={3}>Loading...</Card>
return (
<Card padding={3} radius={2} shadow={1}>
<Stack space={2}>
<Text weight="bold">{value.title}</Text>
{value.subtitle && <Text size={1} muted>{value.subtitle}</Text>}
</Stack>
</Card>
)
}