useProject, useProjects, useOrganization, useOrganizations, and useDatasets return a result objectThese five hooks are now backed by a live re-fetching utility. Instead of returning the fetched value directly, they return a FetcherHookResult: {data, isFetching, error, refetch}. The hook still suspends until the first fetch succeeds, so data is always present once your component renders.
Before:
const project = useProject({projectId})
const projects = useProjects()
const organization = useOrganization({organizationId})
const organizations = useOrganizations()
const datasets = useDatasets()
After:
const {data: project} = useProject({projectId})
const {data: projects} = useProjects()
const {data: organization} = useOrganization({organizationId})
const {data: organizations} = useOrganizations()
const {data: datasets} = useDatasets()
Destructuring in place works the same way:
Before:
const {organizationId, id} = useProject()
After:
const {
data: {organizationId, id},
} = useProject()
No other hooks changed shape.
Fetched data is considered fresh for 30 seconds. After that, the hook serves the cached value immediately and refetches in the background, so a mounted component can receive new data without remounting. In v2 each entry was fetched once and cached for the lifetime of the instance.
If you relied on the value being stable for as long as the component was mounted, read isFetching to tell a background refresh apart from settled data, and use refetch to force a fresh read:
const {data: project, isFetching, refetch} = useProject({projectId})
refetch bypasses the freshness window and resolves with the refreshed data.
Only the initial fetch throws. Once data has rendered, a failed background revalidation is reported through error while the last successful value keeps rendering; the next success clears it. An error boundary alone will no longer surface these failures.
const {data: projects, error} = useProjects()
if (error) {
// stale data is still rendering — surface a refresh warning if you need one
}
@sanity/sdk changed public interfacesThe datasets and favorites stores moved onto the same fetching paradigm that backs the hooks in 1. This means their store-specific functions and the legacy fetcher-store types (getDatasetsState, resolveDatasets, getFavoritesState, resolveFavoritesState, FetcherStore, and FetcherStoreState) have been removed. Most users were likely using the @sanity/sdk-react hooks and are likely not affected (except for the changed return signature of useDatasets mentioned in the first item).
The useDispatchIntent hook and the defineIntent function have been removed, along with the Intent and IntentFilter types.
The other half of this system was never built: defined intents were never registered anywhere, and a dispatched intent had no handler to resolve to. dispatchIntent() sent a window message that nothing listened for, so removing these APIs does not change how your app behaves at runtime.
@sanity/sdk agent and comlink utilities moved to sub-entriesAgent and comlink utilities are now available only from dedicated sub-entry points:
Previously in @sanity/sdk |
Now in |
|---|---|
agentGenerate, agentPatch, agentPrompt, agentTransform, agentTranslate and their option types |
@sanity/sdk/agent |
getOrCreateController, getOrCreateChannel, getOrCreateNode, getNodeState, FrameMessage, etc. |
@sanity/sdk/comlink |
Before:
import {agentGenerate, type AgentGenerateOptions, type FrameMessage} from '@sanity/sdk'
After:
import {agentGenerate, type AgentGenerateOptions} from '@sanity/sdk/agent'
import {type FrameMessage} from '@sanity/sdk/comlink'
@sanity/sdk-react re-exports the main @sanity/sdk entry point, but not these two sub-entries. Make the above code changes to get access to these.
A handful of helpers that only existed to support the React layer are no longer part of the public API: isStudioConfig, getClientErrorApiBody, getClientErrorApiDescription, getClientErrorApiType, isProjectUserNotFoundClientError, ApiErrorBody, PREVIEW_PROJECTION, transformProjectionToPreview, getQueryKey, parseQueryKey, getUsersKey, parseUsersKey, and createGroqSearchFilter.
These were never intended as app-facing APIs and have no stability guarantee. If you depend on one, open an issue describing your use case so we can consider a supported replacement.
source APIs removed in favour of resourcev2 introduced source and then the resource parameter to allow for easier usage of different datasets and also Media Library and Canvas stores. The source alias has been removed:
| Removed | Use instead |
|---|---|
source option on handles |
resource |
sourceName option on hooks |
resourceName |
sources config option |
resources prop on <SanityApp> (see 12) |
DocumentSource, DatasetSource, MediaLibrarySource, CanvasSource |
DocumentResource, DatasetResource, MediaLibraryResource, CanvasResource |
isDatasetSource, isMediaLibrarySource, isCanvasSource |
isDatasetResource, isMediaLibraryResource, isCanvasResource |
Before:
const {data} = useDocuments({sourceName: 'media-library'})
After:
const {data} = useDocuments({resourceName: 'media-library'})
The preview store was superseded by the projection store in v2 for the core package (useDocumentPreview still exists). The deprecated wrappers have been removed:
| Removed | Use instead |
|---|---|
getPreviewState / GetPreviewStateOptions |
getProjectionState with an explicit projection |
resolvePreview / ResolvePreviewOptions |
resolveProjection with an explicit projection |
PreviewStoreState |
Use the return type of getProjectionState |
ValuePending |
Removed — was only used by the old preview API |
The useDocumentPreview hook is unaffected; it has been backed by the projection store since v2.
| Removed | Use instead |
|---|---|
studioMode config option |
studio config option (or zero-config SDKStudioContext) |
ValidProjection type |
string — projection strings are validated at runtime |
sanityConfigs prop on <SanityApp> |
config prop |
ProjectWithoutMembers type |
Project |
useSanityInstance no longer accepts a config argumentPassing a config to match against the instance hierarchy was deprecated in v2 and already had no effect — it logged a warning and returned the context instance regardless. The parameter is now removed.
Before:
const instance = useSanityInstance(myConfig)
After:
const instance = useSanityInstance()
SanityInstance hierarchy is removedSanityInstance.getParent(), SanityInstance.createChild(), and SanityInstance.match() have been removed. SDK apps use a single instance for all resources, so the hierarchy had no remaining purpose.
If you used createChild to scope work to a different project or dataset, pass an explicit resource to the operation instead:
Before:
const child = instance.createChild({projectId: 'other', dataset: 'production'})
applyDocumentActions(child, {actions})
After:
applyDocumentActions(instance, {actions, resource: {projectId: 'other', dataset: 'production'}})
The instance config still acts as the default resource in core. This is unchanged; neither of the two removals above affects it. If you configure a project and dataset when you create the instance, you can keep calling resource-scoped APIs without passing a resource:
const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
// still resolves to {projectId: 'p', dataset: 'd'}
getDocumentState(instance, {documentId: 'doc1', documentType: 'author'})
The same applies to perspective: set it once on the instance and it is used by any call that does not pass its own. An explicit resource or perspective on an individual call always wins over the instance config. This remains the recommended way to use the core SDK directly, without the React layer.
SanityConfig.resources removed; resource is now an effective defaultresources (plural) was a map of named resources on the instance config, but the core SDK package never read it; named-resource lookup is a React-layer feature driven by the resources prop on <SanityApp> / <SDKProvider>, which is unchanged. The config field has been removed.
// Before — had no effect in core
const instance = createSanityInstance({
projectId: 'p',
dataset: 'd',
resources: {'media-library': {mediaLibraryId: 'ml-123'}},
})
// After — named resources stay a React concern
<SanityApp config={{projectId: 'p', dataset: 'd'}} resources={{'media-library': {mediaLibraryId: 'ml-123'}}} />
In its place, resource (singular) on SanityConfig now works as the instance's default resource. Previously it type-checked but was ignored; calls fell back to projectId/dataset regardless. Any call that does not pass its own resource now operates against it:
const instance = createSanityInstance({resource: {mediaLibraryId: 'ml-123'}})
// resolves against the media library — no per-call resource needed
getDocumentState(instance, {documentId, documentType})
Unlike projectId/dataset, this can be a media library or canvas resource, so the whole surface is usable against those without threading a resource through every call. projectId/dataset remain to try to maintain some compatibility with v2, but may be removed in a future version.
const instance = createSanityInstance({
projectId: 'p',
resource: {mediaLibraryId: 'ml-123'},
})
Relatedly, useActiveReleases and useAllReleases now take a DatasetHandle rather than a SanityConfig. Both already ignored the config-only fields, and this keeps them accepting an explicit resource.
Dashboard hooks have moved to the dedicated @sanity/sdk-react/dashboard entry point:
Previously in @sanity/sdk-react |
Now in @sanity/sdk-react/dashboard |
|---|---|
useDashboardOrganizationId |
useOrganizationId |
useDashboardNavigate |
useNavigate |
useNavigateToStudioDocument |
useNavigateToStudioDocument |
useWindowTitle |
useWindowTitle |
useAgentResourceContext |
useAgentResourceContext |
The related types have moved to the same entry point:
Previously in @sanity/sdk-react |
Now in @sanity/sdk-react/dashboard |
|---|---|
AgentResourceContextOptions |
AgentResourceContextOptions |
NavigateToStudioResult |
NavigateToStudioResult |
useManageFavorite split into useFavorite and useUpdateFavoriteuseManageFavorite both read and wrote favorite status. It is replaced by a read hook and a write hook, matching the CRUD naming used by the rest of the SDK. useFavorite returns the boolean status and suspends until it resolves. useUpdateFavorite returns the favorite/unfavorite actions plus {isPending, error, reset} and does not suspend. Both take the same props useManageFavorite did.
Before:
function FavoriteButton(handle: UseFavoriteProps) {
const {favorite, unfavorite, isFavorited} = useManageFavorite(handle)
return (
<Button
onClick={() => (isFavorited ? unfavorite() : favorite())}
text={isFavorited ? 'Remove from favorites' : 'Add to favorites'}
/>
)
}
After:
function FavoriteButton(handle: UseFavoriteProps) {
const isFavorited = useFavorite(handle)
const {favorite, unfavorite} = useUpdateFavorite(handle)
return (
<Button
onClick={() => (isFavorited ? unfavorite() : favorite())}
text={isFavorited ? 'Remove from favorites' : 'Add to favorites'}
/>
)
}
Non-breaking additions:
useCheckPermissions for resource-level permission checks.useApplication, useApplications, useUpdateApplication, and useDeleteApplication.useInstallation and useInstallations.MutationHookResult: {mutate, isPending, error, data, reset}.AuthBoundary no longer redirects to the login URL when running in the dashboard, where the host OS owns the session and mints the token.status to _status in preview and projection resultsThe status field in preview and projection results has been renamed to _status to prevent collisions with user-defined status fields and to follow the convention of using underscore prefix for system attributes.
Before:
const {data} = useDocumentPreview({documentId: '123', documentType: 'product'})
console.log(data?.status?.lastEditedPublishedAt)
After:
const {data} = useDocumentPreview({documentId: '123', documentType: 'product'})
console.log(data?._status?.lastEditedPublishedAt)
This change affects:
PreviewValue interfaceuseManageFavorite, useNavigateToStudioDocument, and useRecordDocumentHistoryEvent now all suspend.Before:
function MyDocumentAction(props: DocumentActionProps) {
const {documentId, documentType, resourceId} = props
const {favorite, unfavorite, isFavorited, isConnected} = useManageFavorite({
documentId,
documentType,
resourceId
})
return (
<Button
disabled={!isConnected}
onClick={() => isFavorited ? unfavorite() : favorite()}
text={isFavorited ? 'Remove from favorites' : 'Add to favorites'}
/>
)
}
After:
function FavoriteButton(props: DocumentActionProps) {
const {documentId, documentType, resourceId} = props
const {favorite, unfavorite, isFavorited} = useManageFavorite({
documentId,
documentType,
resourceId
})
return (
<Button
onClick={() => isFavorited ? unfavorite() : favorite()}
text={isFavorited ? 'Remove from favorites' : 'Add to favorites'}
/>
)
}
// Wrap the component with Suspense since the hook may suspend
function MyDocumentAction(props: DocumentActionProps) {
return (
<Suspense fallback={<Button text="Loading..." disabled />}>
<FavoriteButton {...props} />
</Suspense>
)
}
The following hooks now also suspend and must be wrapped in <Suspense>:
useNavigateToStudioDocumentBefore:
function NavigateButton({documentHandle}: {documentHandle: DocumentHandle}) {
const {navigateToStudioDocument, isConnected} = useNavigateToStudioDocument(documentHandle)
return (
<Button
disabled={!isConnected}
onClick={navigateToStudioDocument}
text="Navigate to Studio Document"
/>
)
}
After:
function NavigateButton({documentHandle}: {documentHandle: DocumentHandle}) {
const {navigateToStudioDocument} = useNavigateToStudioDocument(documentHandle)
return (
<Button
onClick={navigateToStudioDocument}
text="Navigate to Studio Document"
/>
)
}
// Wrap the component with Suspense since the hook may suspend
function MyDocumentAction({documentHandle}: {documentHandle: DocumentHandle}) {
return (
<Suspense fallback={<Button text="Loading..." disabled />}>
<NavigateButton documentHandle={documentHandle} />
</Suspense>
)
}
useRecordDocumentHistoryEventBefore:
function RecordEventButton(props: DocumentActionProps) {
const {documentId, documentType, resourceType, resourceId} = props
const {recordEvent, isConnected} = useRecordDocumentHistoryEvent({
documentId,
documentType,
resourceType,
resourceId,
})
return (
<Button
disabled={!isConnected}
onClick={() => recordEvent('viewed')}
text="Viewed"
/>
)
}
After:
function RecordEventButton(props: DocumentActionProps) {
const {documentId, documentType, resourceType, resourceId} = props
const {recordEvent} = useRecordDocumentHistoryEvent({
documentId,
documentType,
resourceType,
resourceId,
})
return (
<Button
onClick={() => recordEvent('viewed')}
text="Viewed"
/>
)
}
// Wrap the component with Suspense since the hook may suspend
function MyDocumentAction(props: DocumentActionProps) {
return (
<Suspense fallback={<Button text="Loading..." disabled />}>
<RecordEventButton {...props} />
</Suspense>
)
}
Renamed hooks for better clarity and consistency:
usePreview → useDocumentPreviewuseProjection → useDocumentProjectionAlso renamed associated types to match:
UsePreviewOptions → useDocumentPreviewOptionsUsePreviewResults → useDocumentPreviewResultsUseProjectionOptions → useDocumentProjectionOptionsUseProjectionResults → useDocumentProjectionResultsuseDocument return structureThe useDocument hook now returns its data under a data property for consistency with other hooks in the SDK.
Before:
// Full document
const product = useDocument({documentId: '123', documentType: 'product'})
console.log(product?.title)
// Path selection
const title = useDocument({
documentId: '123',
documentType: 'product',
path: 'title',
})
console.log(title)
After:
// Full document - now returns {data: T | null}
const {data: product} = useDocument({documentId: '123', documentType: 'product'})
console.log(product?.title) // product is possibly null
// Path selection - now returns {data: T | undefined}
const {data: title} = useDocument({
documentId: '123',
documentType: 'product',
path: 'title',
})
console.log(title) // title is possibly undefined
This version introduces significant improvements for TypeScript users by integrating Sanity TypeGen. While Typegen is optional, using it unlocks strong type safety for documents, queries, and projections. These changes also refine hook signatures for better consistency, even for JavaScript users.
See the TypeScript guide for full setup and usage details.
DocumentHandle or DatasetHandle.While literal objects still work, using helpers like createDocumentHandle (imported from @sanity/sdk-react) is recommended, especially with TypeScript, to ensure literal types are captured correctly for Typegen.
Before:
// === 🛑 BEFORE ===
// Using literal object
const handle = {
documentId: '123',
documentType: 'book',
dataset: 'production',
projectId: 'abc',
}
After:
// === ✅ AFTER ✨ ===
import {createDocumentHandle} from '@sanity/sdk-react'
// Using helper - recommended
const handle = createDocumentHandle({
documentId: '123',
documentType: 'book',
dataset: 'production',
projectId: 'abc',
})
useQueryAccepts a single options object containing query (defined with defineQuery), params, and optional projectId, dataset, etc.
Before:
// 🛑 BEFORE (does not work)
const {data} = useQuery(
'*[_type == $type]', // Raw query string
{type: 'book'}, // Params
{
// Options object (separate)
projectId: 'abc',
dataset: 'production',
perspective: 'published',
},
)
After:
// === ✅ AFTER ✨ ===
import {defineQuery} from 'groq'
const query = defineQuery('*[_type == $type]') // Defined query
const {data} = useQuery({
// Single options object
query: query,
params: {type: 'book'},
projectId: 'abc', // Optional override
dataset: 'production', // Optional override
perspective: 'published',
})
useDocumentAccepts a single options object, spreading the handle and adding path if needed.
Before:
// === 🛑 BEFORE ===
// Fetching the whole document
const document = useDocument(docHandle)
// Fetching a specific path
const name = useDocument(docHandle, 'name')
After:
// === ✅ AFTER ✨ ===
// Fetching the whole document
const document = useDocument(docHandle)
// const document = useDocument({...docHandle}) // Or spread handle
// Fetching a specific path
const name = useDocument({...docHandle, path: 'name'}) // Spread handle and add path
useEditDocumentAccepts a single options object, spreading the handle and adding path if needed.
Before:
// === 🛑 BEFORE ===
// Get setter for the whole document
const setDocument = useEditDocument(docHandle)
// Get setter for a specific path
const setName = useEditDocument(docHandle, 'name')
After:
// === ✅ AFTER ✨ ===
// Get setter for the whole document
const setDocument = useEditDocument(docHandle)
// const setDocument = useEditDocument({...docHandle}) // Or spread handle
// Get setter for a specific path
const setName = useEditDocument({...docHandle, path: 'name'}) // Spread handle and add path
useDocuments / usePaginatedDocumentsThe filter option can still be used for complex GROQ filters. However, for simple filtering by type, the documentType option is preferred and aligns better with Typegen scoping.
Before (Simple type filter):
// === 🛑 BEFORE ===
const {data} = useDocuments({
filter: '_type == "author"',
orderings: [{field: 'name', direction: 'asc'}],
})
After (Simple type filter):
// === ✅ AFTER ✨ ===
const {data} = useDocuments({
documentType: 'author', // Use documentType for simple type filtering
orderings: [{field: 'name', direction: 'asc'}],
})
Complex Filter (Remains similar):
Before:
// === 🛑 BEFORE === (Complex filter)
const {data} = usePaginatedDocuments({
filter: '_type == "author" && count(favoriteBooks) > 0',
// ... other options
})
After:
// === ✅ AFTER ✨ === (Complex filter - use filter)
const {data} = usePaginatedDocuments({
documentType: 'author', // Can still specify type
filter: 'count(favoriteBooks) > 0', // Add additional filter logic
// ... other options
})
useDocumentEventAccepts a single options object, spreading the handle and adding the onEvent callback.
Before:
// === 🛑 BEFORE ===
useDocumentEvent(onEventCallback, docHandle)
After:
// === ✅ AFTER ✨ ===
useDocumentEvent({...docHandle, onEvent: onEventCallback})
createDocument, editDocument, publishDocument, etc.) and types (DocumentHandle, DatasetHandle, DocumentAction) now use generic type parameters (<TDocumentType, TDataset, TProjectId>) for better type safety with Typegen. Usage generally remains the same, but TypeScript users will see improved type checking.applyDocumentActions similarly uses these generic types and its return type reflects the potentially typed document result (SanityDocumentResult).By adopting these changes, especially defineQuery and defineProjection, you enable the SDK to leverage Typegen for a much safer and more productive development experience, particularly in TypeScript projects.
Removed Authentication Components and Hooks:
<Login /> component - authentication now redirects to sanity.io/login<LoginLayout /> component and its related propsuseLoginUrls hook - replaced with useLoginUrl hook that returns a single login URL<AuthBoundary /> now automatically redirects to sanity.io/login when logged out<LoginCallback /> now renders null during the callback processAuthentication Flow Changes:
Renamed hooks:
useInfiniteList is now useDocumentsusePaginatedList is now usePaginatedDocumentsusePermissions is now useDocumentPermissionsuseApplyActions is now useApplyDocumentActions (and the applyActions function is now applyDocumentActions)Re-exported core SDK: The @sanity/sdk package is now fully re-exported from @sanity/sdk-react. This means you only need to install and import from @sanity/sdk-react to access both React-specific hooks/components and core SDK functions/types. You should update your imports accordingly and remove @sanity/sdk as a direct dependency if it's no longer needed.
Improved component hierarchy with <SanityApp />, <SDKProvider />, and <ResourceProvider />
Simplified document references with explicit projectId + dataset fields
Standardized property names across the SDK
Unified hook interfaces with the handle pattern
We've updated our component hierarchy to provide better flexibility and control over resource management:
<SanityApp />: The recommended top-level component for most applications<SDKProvider />: An intermediate component with authentication boundaries (for advanced use cases)<ResourceProvider />: The foundational component for individual resource configurations<SanityApp />For most applications, particularly dashboard applications, we recommend using the <SanityApp /> component:
// Single project configuration
<SanityApp
config={{projectId: 'abc1235', dataset: 'production'}}
fallback={<>Loading…</>}
>
<App />
</SanityApp>
// Multiple project configuration
<SanityApp
config={[
{projectId: 'abc1235', dataset: 'production'},
{projectId: 'xyz1235', dataset: 'production'},
]}
fallback={<>Loading…</>}
>
<App />
</SanityApp>
The config prop replaces the previous sanityConfigs prop and supports both single and multiple configurations. When providing multiple configurations, the first one in the array will be the default instance.
We've introduced a consistent "handle" pattern across the SDK for working with documents and configuration. This replaces the previous resourceId concept with more explicit fields.
Before:
const doc: DocumentHandle<Author> = {
_type: 'author',
_id: 'db06bc9e-4608-465a-9551-a10cef478037',
resourceId: 'document:ppsg7ml5.test:db06bc9e-4608-465a-9551-a10cef478037',
}
After:
const doc: DocumentHandle<Author> = {
documentType: 'author', // Previously _type
documentId: 'db06bc9e-4608-465a-9551-a10cef478037', // Previously _id
projectId: 'ppsg7ml5', // From resourceId
dataset: 'test', // From resourceId
}
The SDK now uses three main handle types:
// For project-level operations
interface ProjectHandle {
projectId?: string
}
// For dataset-level operations
interface DatasetHandle extends ProjectHandle {
dataset?: string
}
// For document operations
interface DocumentHandle extends DatasetHandle {
documentId: string
documentType: string
}
Various hooks and associated types have been renamed for clarity. Their signatures remain the same, aside from the use of document handles, which is covered in the next section.
useInfiniteList is now useDocumentsInfiniteListOptions is now DocumentsOptionsInfiniteList is now DocumentsResponseusePaginatedList is now usePaginatedDocumentsPaginatedListOptions is now PaginatedDocumentsOptionsPaginatedList is now PaginatedDocumentsResponseuseApplyActions is now useApplyDocumentActionsapplyActions is now applyDocumentActionsApplyActionsOptions is now ApplyDocumentActionsOptionsusePermissions is now useDocumentPermissionsPermissionsResult is now DocumentPermissionsResultMany hooks have been updated to use the handle pattern consistently.
Before:
function Preview({document}: {document: DocumentHandle}) {
const {data} = useProjection({document, projection: '{title}'})
const {data: preview} = usePreview({document, ref: someRef})
return // ...
}
After:
interface PreviewProps extends DocumentHandle {
showExtra?: boolean
}
function Preview({showExtra, ...docHandle}: PreviewProps) {
const ref = useRef<HTMLElement>(null)
const {data} = useProjection({...docHandle, ref, projection: '{title}'})
const {data: preview} = usePreview({...docHandle, ref})
return // ...
}
All query-based hooks now accept DatasetHandle for configuration:
// useQuery with optional project/dataset override
const {data} = useQuery('*[_type == $type][0...10]', {
params: {type: 'author'},
projectId: 'abc12345', // Optional - inherits from ResourceProvider
dataset: 'production', // Optional - inherits from ResourceProvider
})
// List hooks with configuration
const {data: documents} = useDocuments({
filter: '_type == "product"',
projectId: 'xyz12345', // Optional
dataset: 'staging', // Optional
batchSize: 20,
})
// Returned documents include full context
documents.map((docHandle) => (
<DocumentPreview
key={docHandle.documentId}
{...docHandle} // Includes projectId, dataset, etc.
/>
))
Project and dataset hooks now use the handle pattern:
// Before
const project = useProject('abc12345')
// After
const project = useProject({projectId: 'abc12345'})
const datasets = useDatasets({projectId: 'abc12345'})
🔄 Coming Soon: We're continuing to refine our APIs. Future releases will include:
- Further unification of hook signatures
- More consistent parameter naming
- Additional handle pattern improvements
- Enhanced TypeScript types and validations
Authentication Changes:
<Login />, <LoginLayout />, and useLoginUrls<AuthBoundary /> and <LoginCallback /> behavior changesComponent Changes:
<SanityApp /> now uses config instead of sanityConfigs<SDKProvider /> now uses config prop for multiple configurations<ResourceProvider /> provides granular control for single configuration<SanityProvider /> removedHook Renames:
useInfiniteList is now useDocumentsusePaginatedList is now usePaginatedDocumentsusePermissions is now useDocumentPermissionsuseApplyActions is now useApplyDocumentActions (and the applyActions function is now applyDocumentActions)@sanity/sdk Re-exported: All exports from @sanity/sdk are now available directly from @sanity/sdk-react.
Property Renames:
_type → documentType_id → documentIdresults → data (in hook returns)resourceId conceptInterface Updates:
DocumentHandle