Dynamic string options from Sanity document list in schema
You'll need to create a custom input component to achieve dynamic options from Sanity. Unfortunately, you can't use async functions or queries directly in the options.list field of a schema definition - it only accepts static arrays.
Here's how to solve this with a custom input component:
Create a Custom Input Component
First, create a custom input component that fetches pages dynamically using the useClient hook:
// components/PageSelectInput.tsx
import { useClient } from 'sanity'
import { StringInputProps, set, unset } from 'sanity'
import { useEffect, useState } from 'react'
import { Stack, Select } from '@sanity/ui'
export function PageSelectInput(props: StringInputProps) {
const { value, onChange } = props
const client = useClient({ apiVersion: '2024-01-01' })
const [pages, setPages] = useState<Array<{ _id: string; title: string }>>([])
const [loading, setLoading] = useState(true)
useEffect(() => {
// Fetch all pages from Sanity
client
.fetch(`*[_type == "page"]{ _id, title, "slug": slug.current }`)
.then((result) => {
setPages(result)
setLoading(false)
})
.catch((error) => {
console.error('Error fetching pages:', error)
setLoading(false)
})
}, [client])
const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
const newValue = event.target.value
onChange(newValue ? set(newValue) : unset())
}
return (
<Stack space={3}>
<Select
value={value || ''}
onChange={handleChange}
disabled={loading}
>
<option value="">Select a page</option>
{pages.map((page) => (
<option key={page._id} value={page._id}>
{page.title}
</option>
))}
</Select>
</Stack>
)
}Use the Custom Component in Your Schema
Then reference this custom component in your schema:
import { PageSelectInput } from './components/PageSelectInput'
{
name: 'goToPage',
title: 'Go to page',
description: 'This will be the page you would like the users to go to.',
type: 'string',
components: {
input: PageSelectInput
}
}Alternative: Use a Reference Field
If you're storing page IDs anyway, consider using Sanity's built-in reference field instead:
{
name: 'goToPage',
title: 'Go to page',
type: 'reference',
to: [{ type: 'page' }],
options: {
filter: '_type == "page"' // Optional: add custom filters
}
}This gives you a searchable dropdown with all pages automatically, without needing a custom component. The reference field also ensures data integrity and lets you easily resolve the full page document when querying.
The custom input approach gives you more control over the UI and what values are stored (like storing slugs instead of IDs), while the reference approach is simpler and more maintainable for typical use cases where you're linking to other documents.
Show original thread2 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.