Skip to content

Commit a666115

Browse files
committed
address document-context comments
1 parent 998a26f commit a666115

File tree

4 files changed

+41
-27
lines changed

4 files changed

+41
-27
lines changed

packages/react/document-context/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@
2828
"version": "yarn version"
2929
},
3030
"dependencies": {
31-
"@radix-ui/react-primitive": "workspace:*"
31+
"@radix-ui/react-primitive": "workspace:*",
32+
"use-sync-external-store": "^1.4.0"
3233
},
3334
"devDependencies": {
3435
"@repo/typescript-config": "workspace:*",
3536
"@types/react": "^19.0.7",
37+
"@types/use-sync-external-store": "^0.0.6",
3638
"react": "^19.0.0",
3739
"typescript": "^5.7.3"
3840
},

packages/react/document-context/src/document-context.test.tsx

+8-16
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,6 @@ function TestComponent() {
88
}
99

1010
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-
2111
it('provides custom document when specified', () => {
2212
const mockDocument = {} as Document;
2313

@@ -59,18 +49,20 @@ describe('DocumentContext', () => {
5949
expect(screen.getByText('Document ID: 2')).toBeInTheDocument();
6050
});
6151

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', () => {
6353
function TestDocumentConsumer() {
6454
const doc = useDocument();
6555
return <div>{doc === globalThis.document ? 'global document' : 'other document'}</div>;
6656
}
6757

68-
render(
69-
<DocumentProvider>
70-
<TestDocumentConsumer />
71-
</DocumentProvider>
72-
);
58+
render(<TestDocumentConsumer />);
7359

7460
expect(screen.getByText('global document')).toBeInTheDocument();
7561
});
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+
});
7668
});
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
11
import * as React from 'react';
2-
2+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
33
// Use null as initial value to handle SSR safely
44
const DocumentContext = React.createContext<Document | null>(null);
55

66
interface DocumentProviderProps {
7-
document?: Document;
7+
document: Document;
88
children: React.ReactNode;
99
}
1010

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>;
1713
}
1814

15+
const subscribe = () => () => {};
16+
1917
export function useDocument() {
2018
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);
2325
}

yarn.lock

+18
Original file line numberDiff line numberDiff line change
@@ -2073,8 +2073,10 @@ __metadata:
20732073
"@radix-ui/react-primitive": "workspace:*"
20742074
"@repo/typescript-config": "workspace:*"
20752075
"@types/react": "npm:^19.0.7"
2076+
"@types/use-sync-external-store": "npm:^0.0.6"
20762077
react: "npm:^19.0.0"
20772078
typescript: "npm:^5.7.3"
2079+
use-sync-external-store: "npm:^1.4.0"
20782080
peerDependencies:
20792081
"@types/react": "*"
20802082
react: ^16.8 || ^17.0 || ^18.0 || ^19.0
@@ -4534,6 +4536,13 @@ __metadata:
45344536
languageName: node
45354537
linkType: hard
45364538

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+
45374546
"@types/uuid@npm:^9.0.1":
45384547
version: 9.0.8
45394548
resolution: "@types/uuid@npm:9.0.8"
@@ -13437,6 +13446,15 @@ __metadata:
1343713446
languageName: node
1343813447
linkType: hard
1343913448

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+
1344013458
"util-deprecate@npm:^1.0.2":
1344113459
version: 1.0.2
1344213460
resolution: "util-deprecate@npm:1.0.2"

0 commit comments

Comments
 (0)