From 7a531df47d7064fcb5351ad212524e971d984d6c Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 10 May 2022 18:07:53 -0400 Subject: [PATCH 1/3] Obfuscate React.useSyncExternalStore to prevent webpack complaint. https://github.com/apollographql/apollo-client/pull/9675#issuecomment-1122033281 --- src/react/hooks/useSyncExternalStore.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/react/hooks/useSyncExternalStore.ts b/src/react/hooks/useSyncExternalStore.ts index 7f72f7d91c6..6b6677567ac 100644 --- a/src/react/hooks/useSyncExternalStore.ts +++ b/src/react/hooks/useSyncExternalStore.ts @@ -12,6 +12,13 @@ type RealUseSESHookType = // when only React 17 or earlier is installed. typeof import("use-sync-external-store").useSyncExternalStore; +// Prevent webpack from complaining about our feature detection of the +// useSyncExternalStore property of the React namespace, which is expected not +// to exist when using React 17 and earlier, and that's fine. +const obfuscatedReactNamespace: typeof React & { + useSyncExternalStore?: RealUseSESHookType; +} = React; + // Adapted from https://www.npmjs.com/package/use-sync-external-store, with // Apollo Client deviations called out by "// DEVIATION ..." comments. @@ -21,9 +28,7 @@ export const useSyncExternalStore: RealUseSESHookType = ( getServerSnapshot, ) => { // When/if React.useSyncExternalStore is defined, delegate fully to it. - const realHook = (React as { - useSyncExternalStore?: RealUseSESHookType; - }).useSyncExternalStore; + const realHook = obfuscatedReactNamespace.useSyncExternalStore; if (realHook) { return realHook(subscribe, getSnapshot, getServerSnapshot); } From 50fd0bdaf486ebd8b40d899303b9b5afc86e6b29 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 10 May 2022 18:18:16 -0400 Subject: [PATCH 2/3] Commit to realHook in module scope. --- src/react/hooks/useSyncExternalStore.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/react/hooks/useSyncExternalStore.ts b/src/react/hooks/useSyncExternalStore.ts index 6b6677567ac..55e5a71dddc 100644 --- a/src/react/hooks/useSyncExternalStore.ts +++ b/src/react/hooks/useSyncExternalStore.ts @@ -15,24 +15,18 @@ type RealUseSESHookType = // Prevent webpack from complaining about our feature detection of the // useSyncExternalStore property of the React namespace, which is expected not // to exist when using React 17 and earlier, and that's fine. -const obfuscatedReactNamespace: typeof React & { - useSyncExternalStore?: RealUseSESHookType; -} = React; +const uSESKey = "useSyncExternalStore" as keyof typeof React; +const realHook = React[uSESKey] as RealUseSESHookType | undefined; // Adapted from https://www.npmjs.com/package/use-sync-external-store, with // Apollo Client deviations called out by "// DEVIATION ..." comments. -export const useSyncExternalStore: RealUseSESHookType = ( +// When/if React.useSyncExternalStore is defined, delegate fully to it. +export const useSyncExternalStore: RealUseSESHookType = realHook || (( subscribe, getSnapshot, getServerSnapshot, ) => { - // When/if React.useSyncExternalStore is defined, delegate fully to it. - const realHook = obfuscatedReactNamespace.useSyncExternalStore; - if (realHook) { - return realHook(subscribe, getSnapshot, getServerSnapshot); - } - // Read the current snapshot from the store on every render. Again, this // breaks the rules of React, and only works here because of specific // implementation details, most importantly that updates are @@ -117,7 +111,7 @@ export const useSyncExternalStore: RealUseSESHookType = ( }, [subscribe]); return value; -} +}); function checkIfSnapshotChanged({ value, From 7c7503fc6ae1da0a590cd90717a640935588de7c Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 10 May 2022 18:25:56 -0400 Subject: [PATCH 3/3] Move @types/use-sync-external-store to devDependencies. This should be safe because we do not export the useSyncExternalStore hook publicly. --- package-lock.json | 8 +++++--- package.json | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 829199df05c..4e418b4808b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "license": "MIT", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", - "@types/use-sync-external-store": "^0.0.3", "@wry/context": "^0.6.0", "@wry/equality": "^0.5.0", "@wry/trie": "^0.3.0", @@ -38,6 +37,7 @@ "@types/node": "16.11.33", "@types/react": "17.0.45", "@types/react-dom": "17.0.16", + "@types/use-sync-external-store": "^0.0.3", "acorn": "8.7.1", "bundlesize": "0.18.1", "cross-fetch": "3.1.5", @@ -1382,7 +1382,8 @@ "node_modules/@types/use-sync-external-store": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", - "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==", + "dev": true }, "node_modules/@types/yargs": { "version": "16.0.4", @@ -7490,7 +7491,8 @@ "@types/use-sync-external-store": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", - "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==", + "dev": true }, "@types/yargs": { "version": "16.0.4", diff --git a/package.json b/package.json index aa2d3d56e8f..0ce7a44f4e3 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,6 @@ }, "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", - "@types/use-sync-external-store": "^0.0.3", "@wry/context": "^0.6.0", "@wry/equality": "^0.5.0", "@wry/trie": "^0.3.0", @@ -109,6 +108,7 @@ "@types/node": "16.11.33", "@types/react": "17.0.45", "@types/react-dom": "17.0.16", + "@types/use-sync-external-store": "^0.0.3", "acorn": "8.7.1", "bundlesize": "0.18.1", "cross-fetch": "3.1.5",