From 34330453cf46c845b2498d151bab71e7d74e98f9 Mon Sep 17 00:00:00 2001 From: Dominik Dorfmeister Date: Thu, 16 Dec 2021 19:52:24 +0100 Subject: [PATCH] feat: remove logging in prod mode to not log to the console per default; to access process.ENV, we need to enable node typings, which screws with setTimeout / setInterval, as typings are different for node and the browser; I tried to keep the changes to type-level only --- .../pages/guides/migrating-to-react-query-4.md | 5 +++++ src/core/mutation.ts | 5 +++-- src/core/query.ts | 15 +++++++++++++-- src/core/queryObserver.ts | 16 ++++++++++------ src/core/removable.ts | 4 ++-- src/core/tests/queriesObserver.test.tsx | 13 +++++++++++++ src/core/tests/utils.test.tsx | 2 +- src/createAsyncStoragePersister/index.ts | 2 +- src/createWebStoragePersister/index.ts | 2 +- tsconfig.json | 2 +- 10 files changed, 50 insertions(+), 16 deletions(-) diff --git a/docs/src/pages/guides/migrating-to-react-query-4.md b/docs/src/pages/guides/migrating-to-react-query-4.md index 6d1535a19e..8bffe466f3 100644 --- a/docs/src/pages/guides/migrating-to-react-query-4.md +++ b/docs/src/pages/guides/migrating-to-react-query-4.md @@ -247,6 +247,11 @@ The methods `cancelMutatations` and `executeMutation` were undocumented and unus Types now require using TypeScript v4.1 or greater +### Logging + +Starting with v4, react-query will no longer log errors (e.g. failed fetches) to the console in production mode, as this was confusing to many. +Errors will still show up in development mode. + ## New Features 🚀 ### Proper offline support diff --git a/src/core/mutation.ts b/src/core/mutation.ts index 04533c11ea..cc0f1e80d5 100644 --- a/src/core/mutation.ts +++ b/src/core/mutation.ts @@ -235,8 +235,9 @@ export class Mutation< this as Mutation ) - // Log error - getLogger().error(error) + if (process.env.NODE_ENV !== 'production') { + getLogger().error(error) + } return Promise.resolve() .then(() => diff --git a/src/core/query.ts b/src/core/query.ts index 07e171ecc7..f82b0281f6 100644 --- a/src/core/query.ts +++ b/src/core/query.ts @@ -367,6 +367,16 @@ export class Query< } } + if ( + process.env.NODE_ENV !== 'production' && + !Array.isArray(this.options.queryKey) + ) { + getLogger().error( + 'As of v4, queryKey needs to be an Array, but the queryKey used was:', + JSON.stringify(this.options.queryKey) + ) + } + const abortController = getAbortController() // Create query function context @@ -459,8 +469,9 @@ export class Query< // Notify cache callback this.cache.config.onError?.(error, this as Query) - // Log error - getLogger().error(error) + if (process.env.NODE_ENV !== 'production') { + getLogger().error(error) + } } if (!this.isFetchingOptimistic) { diff --git a/src/core/queryObserver.ts b/src/core/queryObserver.ts index 2d48d76ec3..eb45719830 100644 --- a/src/core/queryObserver.ts +++ b/src/core/queryObserver.ts @@ -69,8 +69,8 @@ export class QueryObserver< > private previousQueryResult?: QueryObserverResult private previousSelectError: TError | null - private staleTimeoutId?: number - private refetchIntervalId?: number + private staleTimeoutId?: ReturnType + private refetchIntervalId?: ReturnType private currentRefetchInterval?: number | false private trackedProps!: Set @@ -397,12 +397,12 @@ export class QueryObserver< } private clearStaleTimeout(): void { - clearTimeout(this.staleTimeoutId) + clearTimeout(this.staleTimeoutId!) this.staleTimeoutId = undefined } private clearRefetchInterval(): void { - clearInterval(this.refetchIntervalId) + clearInterval(this.refetchIntervalId!) this.refetchIntervalId = undefined } @@ -484,7 +484,9 @@ export class QueryObserver< } this.previousSelectError = null } catch (selectError) { - getLogger().error(selectError) + if (process.env.NODE_ENV !== 'production') { + getLogger().error(selectError) + } error = selectError as TError this.previousSelectError = selectError as TError errorUpdatedAt = Date.now() @@ -527,7 +529,9 @@ export class QueryObserver< } this.previousSelectError = null } catch (selectError) { - getLogger().error(selectError) + if (process.env.NODE_ENV !== 'production') { + getLogger().error(selectError) + } error = selectError as TError this.previousSelectError = selectError as TError errorUpdatedAt = Date.now() diff --git a/src/core/removable.ts b/src/core/removable.ts index c33f08202c..eea3e682bc 100644 --- a/src/core/removable.ts +++ b/src/core/removable.ts @@ -2,7 +2,7 @@ import { isValidTimeout } from './utils' export abstract class Removable { cacheTime!: number - private gcTimeout?: number + private gcTimeout?: ReturnType destroy(): void { this.clearGcTimeout() @@ -27,7 +27,7 @@ export abstract class Removable { } protected clearGcTimeout() { - clearTimeout(this.gcTimeout) + clearTimeout(this.gcTimeout!) this.gcTimeout = undefined } diff --git a/src/core/tests/queriesObserver.test.tsx b/src/core/tests/queriesObserver.test.tsx index 7bf5eef376..27c1d0fdfd 100644 --- a/src/core/tests/queriesObserver.test.tsx +++ b/src/core/tests/queriesObserver.test.tsx @@ -5,6 +5,8 @@ import { QueriesObserver, QueryObserverResult, QueryObserver, + Logger, + setLogger, } from '../..' import { QueryKey } from '..' @@ -39,6 +41,14 @@ describe('queriesObserver', () => { }) test('should still return value for undefined query key', async () => { + const logger: Logger = { + error: jest.fn(), + log: jest.fn(), + warn: jest.fn(), + } + + setLogger(logger) + const key1 = queryKey() const queryFn1 = jest.fn().mockReturnValue(1) const queryFn2 = jest.fn().mockReturnValue(2) @@ -53,6 +63,9 @@ describe('queriesObserver', () => { await sleep(1) unsubscribe() expect(observerResult).toMatchObject([{ data: 1 }, { data: 2 }]) + + expect(logger.error).toHaveBeenCalledTimes(1) + setLogger(console) }) test('should update when a query updates', async () => { diff --git a/src/core/tests/utils.test.tsx b/src/core/tests/utils.test.tsx index 2297c2a6b7..af8b618a82 100644 --- a/src/core/tests/utils.test.tsx +++ b/src/core/tests/utils.test.tsx @@ -379,7 +379,7 @@ describe('core/utils', () => { // Do no throw an uncaught exception that cannot be tested with // this jest version } - return 0 + return 0 as any }) scheduleMicrotask(callback) jest.runAllTimers() diff --git a/src/createAsyncStoragePersister/index.ts b/src/createAsyncStoragePersister/index.ts index 96731076c6..9a1b7b6677 100644 --- a/src/createAsyncStoragePersister/index.ts +++ b/src/createAsyncStoragePersister/index.ts @@ -58,7 +58,7 @@ function asyncThrottle( if (typeof func !== 'function') throw new Error('argument is not function.') const running = { current: false } let lastTime = 0 - let timeout: number + let timeout: ReturnType const queue: Array = [] return (...args: Args) => (async () => { diff --git a/src/createWebStoragePersister/index.ts b/src/createWebStoragePersister/index.ts index e2f61c1d65..a6493b707f 100644 --- a/src/createWebStoragePersister/index.ts +++ b/src/createWebStoragePersister/index.ts @@ -96,7 +96,7 @@ function throttle( func: (...args: TArgs) => any, wait = 100 ) { - let timer: number | null = null + let timer: ReturnType | null = null let params: TArgs return function (...args: TArgs) { params = args diff --git a/tsconfig.json b/tsconfig.json index c88aaec9bd..34a78d8b10 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,7 @@ "noUncheckedIndexedAccess": true, "skipLibCheck": true, "strict": true, - "types": ["jest"], + "types": ["jest", "node"], "paths": { "react-query": ["./src/index.ts"] }