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,63 @@ 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+ let result = < Suspense fallback = { fallback } > { children } </ Suspense >
43+
44+ if ( perspective ) {
45+ result = < PerspectiveContext . Provider value = { perspective } > { result } </ PerspectiveContext . Provider >
46+ }
47+
48+ if ( projectId || dataset ) {
49+ if ( ! ( projectId && dataset ) ) {
50+ throw new Error ( 'SDKProvider requires either both of projectId/dataset or none.' )
4251 }
4352
44- return (
45- < ResourceProvider { ...configs [ index ] } fallback = { fallback } >
46- { createNestedProviders ( index + 1 ) }
47- </ ResourceProvider >
53+ result = (
54+ < DefaultSourceContext value = { sourceFor ( { projectId, dataset} ) } > { result } </ DefaultSourceContext >
4855 )
4956 }
5057
51- return createNestedProviders ( 0 )
58+ const instance = useMemo ( ( ) => createSanityInstance ( mainConfig ) , [ mainConfig ] )
59+
60+ // Ref to hold the scheduled disposal timer.
61+ const disposal = useRef < {
62+ instance : SanityInstance
63+ timeoutId : ReturnType < typeof setTimeout >
64+ } | null > ( null )
65+
66+ useEffect ( ( ) => {
67+ // If the component remounts quickly (as in Strict Mode), cancel any pending disposal.
68+ if ( disposal . current !== null && instance === disposal . current . instance ) {
69+ clearTimeout ( disposal . current . timeoutId )
70+ disposal . current = null
71+ }
72+
73+ return ( ) => {
74+ disposal . current = {
75+ instance,
76+ timeoutId : setTimeout ( ( ) => {
77+ if ( ! instance . isDisposed ( ) ) {
78+ instance . dispose ( )
79+ }
80+ } , 0 ) ,
81+ }
82+ }
83+ } , [ instance ] )
84+
85+ return (
86+ < AuthBoundary { ...props } >
87+ < SanityInstanceContext value = { instance } > { result } </ SanityInstanceContext >
88+ </ AuthBoundary >
89+ )
5290}
0 commit comments