File tree 4 files changed +41
-27
lines changed
packages/react/document-context
4 files changed +41
-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
}
Original file line number Diff line number Diff line change @@ -2073,8 +2073,10 @@ __metadata:
2073
2073
" @radix-ui/react-primitive " : " workspace:*"
2074
2074
" @repo/typescript-config " : " workspace:*"
2075
2075
" @types/react " : " npm:^19.0.7"
2076
+ " @types/use-sync-external-store " : " npm:^0.0.6"
2076
2077
react : " npm:^19.0.0"
2077
2078
typescript : " npm:^5.7.3"
2079
+ use-sync-external-store : " npm:^1.4.0"
2078
2080
peerDependencies :
2079
2081
" @types/react " : " *"
2080
2082
react : ^16.8 || ^17.0 || ^18.0 || ^19.0
@@ -4534,6 +4536,13 @@ __metadata:
4534
4536
languageName : node
4535
4537
linkType : hard
4536
4538
4539
+ " @types/use-sync-external-store@npm:^0.0.6 " :
4540
+ version : 0.0.6
4541
+ resolution : " @types/use-sync-external-store@npm:0.0.6"
4542
+ checksum : 10/a95ce330668501ad9b1c5b7f2b14872ad201e552a0e567787b8f1588b22c7040c7c3d80f142cbb9f92d13c4ea41c46af57a20f2af4edf27f224d352abcfe4049
4543
+ languageName : node
4544
+ linkType : hard
4545
+
4537
4546
" @types/uuid@npm:^9.0.1 " :
4538
4547
version : 9.0.8
4539
4548
resolution : " @types/uuid@npm:9.0.8"
@@ -13437,6 +13446,15 @@ __metadata:
13437
13446
languageName : node
13438
13447
linkType : hard
13439
13448
13449
+ " use-sync-external-store@npm:^1.4.0 " :
13450
+ version : 1.4.0
13451
+ resolution : " use-sync-external-store@npm:1.4.0"
13452
+ peerDependencies :
13453
+ react : ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
13454
+ checksum : 10/08bf581a8a2effaefc355e9d18ed025d436230f4cc973db2f593166df357cf63e47b9097b6e5089b594758bde322e1737754ad64905e030d70f8ff7ee671fd01
13455
+ languageName : node
13456
+ linkType : hard
13457
+
13440
13458
" util-deprecate@npm:^1.0.2 " :
13441
13459
version : 1.0.2
13442
13460
resolution : " util-deprecate@npm:1.0.2"
You can’t perform that action at this time.
0 commit comments