1- import { type SanityConfig } from '@sanity/sdk'
2- import { type ReactElement , type ReactNode } from 'react'
1+ import { createSanityInstance , type SanityConfig , type SanityInstance , sourceFor } from '@sanity/sdk'
2+ import { type ReactElement , type ReactNode , Suspense , useEffect , useMemo , useRef } from 'react'
33
4- import { ResourceProvider } from '../context/ResourceProvider'
4+ import { DefaultSourceContext } from '../context/DefaultSourceContext'
5+ import { PerspectiveContext } from '../context/PerspectiveContext'
6+ import { SanityInstanceContext } from '../context/SanityInstanceContext'
57import { AuthBoundary , type AuthBoundaryProps } from './auth/AuthBoundary'
68
79/**
@@ -26,27 +28,67 @@ export function SDKProvider({
2628 fallback,
2729 ...props
2830} : SDKProviderProps ) : ReactElement {
29- // reverse because we want the first config to be the default, but the
30- // ResourceProvider nesting makes the last one the default
31- const configs = ( Array . isArray ( config ) ? config : [ config ] ) . slice ( ) . reverse ( )
32- const projectIds = configs . map ( ( c ) => c . projectId ) . filter ( ( id ) : id is string => ! ! id )
33-
34- // Create a nested structure of ResourceProviders for each config
35- const createNestedProviders = ( index : number ) : ReactElement => {
36- if ( index >= configs . length ) {
37- return (
38- < AuthBoundary { ...props } projectIds = { projectIds } >
39- { children }
40- </ AuthBoundary >
41- )
31+ if ( Array . isArray ( config ) ) {
32+ // eslint-disable-next-line no-console
33+ console . warn (
34+ '<SDKProvider>: Multiple configs are no longer supported. Only the first one will be used.' ,
35+ )
36+ }
37+
38+ const { projectId, dataset, perspective, ...mainConfig } = Array . isArray ( config )
39+ ? config [ 0 ] || { }
40+ : config
41+
42+ const instance = useMemo ( ( ) => createSanityInstance ( mainConfig ) , [ mainConfig ] )
43+
44+ // Ref to hold the scheduled disposal timer.
45+ const disposal = useRef < {
46+ instance : SanityInstance
47+ timeoutId : ReturnType < typeof setTimeout >
48+ } | null > ( null )
49+
50+ useEffect ( ( ) => {
51+ // If the component remounts quickly (as in Strict Mode), cancel any pending disposal.
52+ if ( disposal . current !== null && instance === disposal . current . instance ) {
53+ clearTimeout ( disposal . current . timeoutId )
54+ disposal . current = null
55+ }
56+
57+ return ( ) => {
58+ disposal . current = {
59+ instance,
60+ timeoutId : setTimeout ( ( ) => {
61+ if ( ! instance . isDisposed ( ) ) {
62+ instance . dispose ( )
63+ }
64+ } , 0 ) ,
65+ }
66+ }
67+ } , [ instance ] )
68+
69+ let result = (
70+ < SanityInstanceContext . Provider value = { instance } >
71+ < Suspense fallback = { fallback } >
72+ < AuthBoundary { ...props } > { children } </ AuthBoundary >
73+ </ Suspense >
74+ </ SanityInstanceContext . Provider >
75+ )
76+
77+ if ( perspective ) {
78+ result = < PerspectiveContext . Provider value = { perspective } > { result } </ PerspectiveContext . Provider >
79+ }
80+
81+ if ( projectId || dataset ) {
82+ if ( ! ( projectId && dataset ) ) {
83+ throw new Error ( 'SDKProvider requires either both of projectId/dataset or none.' )
4284 }
4385
44- return (
45- < ResourceProvider { ... configs [ index ] } fallback = { fallback } >
46- { createNestedProviders ( index + 1 ) }
47- </ ResourceProvider >
86+ result = (
87+ < DefaultSourceContext . Provider value = { sourceFor ( { projectId , dataset } ) } >
88+ { result }
89+ </ DefaultSourceContext . Provider >
4890 )
4991 }
5092
51- return createNestedProviders ( 0 )
93+ return result
5294}
0 commit comments