diff --git a/.eslintrc b/.eslintrc index 97c3fc3abd..0f12e68cd5 100644 --- a/.eslintrc +++ b/.eslintrc @@ -6,6 +6,7 @@ "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "plugin:import/typescript", + "plugin:no-typeof-window-undefined/recommended", "react-app", "prettier" ], diff --git a/docs/guides/window-focus-refetching.md b/docs/guides/window-focus-refetching.md index 22a25106be..bee127abc5 100644 --- a/docs/guides/window-focus-refetching.md +++ b/docs/guides/window-focus-refetching.md @@ -39,7 +39,7 @@ In rare circumstances, you may want to manage your own window focus events that ```tsx focusManager.setEventListener(handleFocus => { // Listen to visibilitychange and focus - if (typeof window !== 'undefined' && window.addEventListener) { + if (typeof document !== 'undefined' && window.addEventListener) { window.addEventListener('visibilitychange', handleFocus, false) window.addEventListener('focus', handleFocus, false) } diff --git a/docs/reference/focusManager.md b/docs/reference/focusManager.md index ad251bd9ee..87fb059cc3 100644 --- a/docs/reference/focusManager.md +++ b/docs/reference/focusManager.md @@ -22,7 +22,7 @@ import { focusManager } from '@tanstack/react-query' focusManager.setEventListener(handleFocus => { // Listen to visibilitychange and focus - if (typeof window !== 'undefined' && window.addEventListener) { + if (typeof document !== 'undefined' && window.addEventListener) { window.addEventListener('visibilitychange', handleFocus, false) window.addEventListener('focus', handleFocus, false) } diff --git a/examples/react/prefetching/pages/[user]/[repo].js b/examples/react/prefetching/pages/[user]/[repo].js index adb1dcca93..c8a278b9f9 100755 --- a/examples/react/prefetching/pages/[user]/[repo].js +++ b/examples/react/prefetching/pages/[user]/[repo].js @@ -6,7 +6,7 @@ import { useQuery } from '@tanstack/react-query' export default () => { const id = - typeof window !== 'undefined' ? window.location.pathname.slice(1) : '' + typeof document !== 'undefined' ? window.location.pathname.slice(1) : '' const { status, data, error, isFetching } = useQuery(['team', id], () => fetch('/api/data?id=' + id), diff --git a/package.json b/package.json index 6bf590c152..daa39b214d 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "eslint-plugin-flowtype": "5.x", "eslint-plugin-import": "^2.22.1", "eslint-plugin-jsx-a11y": "6.x", + "eslint-plugin-no-typeof-window-undefined": "^0.0.2", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.1.3", "eslint-plugin-promise": "^4.2.1", diff --git a/packages/react-query-devtools/src/devtools.tsx b/packages/react-query-devtools/src/devtools.tsx index 0f846f2790..9e658bbc3e 100644 --- a/packages/react-query-devtools/src/devtools.tsx +++ b/packages/react-query-devtools/src/devtools.tsx @@ -282,7 +282,7 @@ export function ReactQueryDevtools({ run() - if (typeof window !== 'undefined') { + if (typeof document !== 'undefined') { window.addEventListener('resize', run) return () => { diff --git a/packages/react-query-devtools/src/useMediaQuery.ts b/packages/react-query-devtools/src/useMediaQuery.ts index fd717b1038..76ed4643f6 100644 --- a/packages/react-query-devtools/src/useMediaQuery.ts +++ b/packages/react-query-devtools/src/useMediaQuery.ts @@ -3,14 +3,14 @@ import * as React from 'react' export default function useMediaQuery(query: string): boolean | undefined { // Keep track of the preference in state, start with the current match const [isMatch, setIsMatch] = React.useState(() => { - if (typeof window !== 'undefined') { + if (typeof document !== 'undefined') { return window.matchMedia(query).matches } }) // Watch for changes React.useEffect(() => { - if (typeof window !== 'undefined') { + if (typeof document !== 'undefined') { // Create a matcher const matcher = window.matchMedia(query) diff --git a/packages/react-query/src/QueryClientProvider.tsx b/packages/react-query/src/QueryClientProvider.tsx index 33a14f69cc..bddd104164 100644 --- a/packages/react-query/src/QueryClientProvider.tsx +++ b/packages/react-query/src/QueryClientProvider.tsx @@ -28,7 +28,7 @@ function getQueryClientContext( if (context) { return context } - if (contextSharing && typeof window !== 'undefined') { + if (contextSharing && typeof document !== 'undefined') { if (!window.ReactQueryClientContext) { window.ReactQueryClientContext = defaultContext } diff --git a/packages/react-query/src/__tests__/QueryClientProvider.test.tsx b/packages/react-query/src/__tests__/QueryClientProvider.test.tsx index 32c1d67020..dd72ccd573 100644 --- a/packages/react-query/src/__tests__/QueryClientProvider.test.tsx +++ b/packages/react-query/src/__tests__/QueryClientProvider.test.tsx @@ -246,6 +246,11 @@ describe('QueryClientProvider', () => { }) test('should not use window to get the context when contextSharing is true and window does not exist', () => { + const { document } = globalThis + + // @ts-expect-error + delete globalThis.document + const queryCache = new QueryCache() const queryClient = createQueryClient({ queryCache }) @@ -269,6 +274,7 @@ describe('QueryClientProvider', () => { expect(queryClientFromHook).toEqual(queryClient) + globalThis.document = document windowSpy.mockRestore() }) }) diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index 48688fe977..caedb26c95 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -32,7 +32,7 @@ function getQueryClientContext( if (context) { return context } - if (contextSharing && typeof window !== 'undefined') { + if (contextSharing && typeof document !== 'undefined') { if (!window.SolidQueryClientContext) { window.SolidQueryClientContext = defaultContext } diff --git a/packages/vue-query/src/vueQueryPlugin.ts b/packages/vue-query/src/vueQueryPlugin.ts index 5d5478791f..6b9794358a 100644 --- a/packages/vue-query/src/vueQueryPlugin.ts +++ b/packages/vue-query/src/vueQueryPlugin.ts @@ -38,7 +38,7 @@ export const VueQueryPlugin = { if ('queryClient' in options && options.queryClient) { client = options.queryClient } else { - if (options.contextSharing && typeof window !== 'undefined') { + if (options.contextSharing && typeof document !== 'undefined') { if (!window.__VUE_QUERY_CONTEXT__) { const clientConfig = 'queryClientConfig' in options diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4c4bf04bb8..2f8386498c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,7 @@ importers: eslint-plugin-flowtype: 5.x eslint-plugin-import: ^2.22.1 eslint-plugin-jsx-a11y: 6.x + eslint-plugin-no-typeof-window-undefined: ^0.0.2 eslint-plugin-node: ^11.1.0 eslint-plugin-prettier: ^3.1.3 eslint-plugin-promise: ^4.2.1 @@ -113,6 +114,7 @@ importers: eslint-plugin-flowtype: 5.10.0_eslint@7.32.0 eslint-plugin-import: 2.26.0_r6mdt2nwtavxychxvtdgpnclqq eslint-plugin-jsx-a11y: 6.6.0_eslint@7.32.0 + eslint-plugin-no-typeof-window-undefined: 0.0.2_eslint@7.32.0 eslint-plugin-node: 11.1.0_eslint@7.32.0 eslint-plugin-prettier: 3.4.1_rpj2lnfnqon5xeujjqgixljdgq eslint-plugin-promise: 4.3.1 @@ -9000,6 +9002,14 @@ packages: semver: 6.3.0 dev: true + /eslint-plugin-no-typeof-window-undefined/0.0.2_eslint@7.32.0: + resolution: {integrity: sha512-CVc5I2RcBkdir5UIahglMh8KYvyFKt9ZbsMFt7WUP+jKXGjS2uCPnbbOQGihTwAFA+tp5F3N6FIuOzIfWNLL1Q==} + peerDependencies: + eslint: ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + eslint: 7.32.0 + dev: true + /eslint-plugin-node/11.1.0_eslint@7.32.0: resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} engines: {node: '>=8.10.0'}