File tree Expand file tree Collapse file tree 3 files changed +23
-27
lines changed
packages/react/document-context Expand file tree Collapse file tree 3 files changed +23
-27
lines changed Original file line number Diff line number Diff line change 28
28
"version" : " yarn version"
29
29
},
30
30
"dependencies" : {
31
- "@radix-ui/react-primitive" : " workspace:*"
31
+ "@radix-ui/react-primitive" : " workspace:*" ,
32
+ "use-sync-external-store" : " ^1.4.0"
32
33
},
33
34
"devDependencies" : {
34
35
"@repo/typescript-config" : " workspace:*" ,
35
36
"@types/react" : " ^19.0.7" ,
37
+ "@types/use-sync-external-store" : " ^0.0.6" ,
36
38
"react" : " ^19.0.0" ,
37
39
"typescript" : " ^5.7.3"
38
40
},
Original file line number Diff line number Diff line change @@ -8,16 +8,6 @@ function TestComponent() {
8
8
}
9
9
10
10
describe ( 'DocumentContext' , ( ) => {
11
- it ( 'provides default document when no custom document is provided' , ( ) => {
12
- render (
13
- < DocumentProvider >
14
- < TestComponent />
15
- </ DocumentProvider >
16
- ) ;
17
-
18
- expect ( screen . getByText ( 'Has document: true' ) ) . toBeInTheDocument ( ) ;
19
- } ) ;
20
-
21
11
it ( 'provides custom document when specified' , ( ) => {
22
12
const mockDocument = { } as Document ;
23
13
@@ -59,18 +49,20 @@ describe('DocumentContext', () => {
59
49
expect ( screen . getByText ( 'Document ID: 2' ) ) . toBeInTheDocument ( ) ;
60
50
} ) ;
61
51
62
- it ( 'provides global document when no value is passed to provider' , ( ) => {
52
+ it ( 'useDocument returns global document when no value is passed to provider' , ( ) => {
63
53
function TestDocumentConsumer ( ) {
64
54
const doc = useDocument ( ) ;
65
55
return < div > { doc === globalThis . document ? 'global document' : 'other document' } </ div > ;
66
56
}
67
57
68
- render (
69
- < DocumentProvider >
70
- < TestDocumentConsumer />
71
- </ DocumentProvider >
72
- ) ;
58
+ render ( < TestDocumentConsumer /> ) ;
73
59
74
60
expect ( screen . getByText ( 'global document' ) ) . toBeInTheDocument ( ) ;
75
61
} ) ;
62
+
63
+ it ( 'useDocument returns default document when custom document is not provided' , ( ) => {
64
+ render ( < TestComponent /> ) ;
65
+
66
+ expect ( screen . getByText ( 'Has document: true' ) ) . toBeInTheDocument ( ) ;
67
+ } ) ;
76
68
} ) ;
Original file line number Diff line number Diff line change 1
1
import * as React from 'react' ;
2
-
2
+ import { useSyncExternalStore } from 'use-sync-external-store/shim' ;
3
3
// Use null as initial value to handle SSR safely
4
4
const DocumentContext = React . createContext < Document | null > ( null ) ;
5
5
6
6
interface DocumentProviderProps {
7
- document ? : Document ;
7
+ document : Document ;
8
8
children : React . ReactNode ;
9
9
}
10
10
11
- export function DocumentProvider ( { document : doc , children } : DocumentProviderProps ) {
12
- const value = React . useMemo (
13
- ( ) => doc ?? ( typeof document !== 'undefined' ? globalThis ?. document : null ) ,
14
- [ doc ]
15
- ) ;
16
- return < DocumentContext . Provider value = { value } > { children } </ DocumentContext . Provider > ;
11
+ export function DocumentProvider ( { document, children } : DocumentProviderProps ) {
12
+ return < DocumentContext . Provider value = { document } > { children } </ DocumentContext . Provider > ;
17
13
}
18
14
15
+ const subscribe = ( ) => ( ) => { } ;
16
+
19
17
export function useDocument ( ) {
20
18
const doc = React . useContext ( DocumentContext ) ;
21
- // Return default document if available and no context value
22
- return doc ?? ( typeof document !== 'undefined' ? globalThis ?. document : null ) ;
19
+ const isHydrated = useSyncExternalStore (
20
+ subscribe ,
21
+ ( ) => true ,
22
+ ( ) => false
23
+ ) ;
24
+ return doc ?? ( isHydrated ? document : null ) ;
23
25
}
You can’t perform that action at this time.
0 commit comments