Skip to content

Commit 9a20452

Browse files
authored
refactor: remove logging in prod mode (#3103)
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
1 parent c53e5ed commit 9a20452

File tree

10 files changed

+50
-16
lines changed

10 files changed

+50
-16
lines changed

docs/src/pages/guides/migrating-to-react-query-4.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,11 @@ The methods `cancelMutatations` and `executeMutation` were undocumented and unus
247247

248248
Types now require using TypeScript v4.1 or greater
249249

250+
### Logging
251+
252+
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.
253+
Errors will still show up in development mode.
254+
250255
## New Features 🚀
251256

252257
### Proper offline support

src/core/mutation.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,9 @@ export class Mutation<
235235
this as Mutation<unknown, unknown, unknown, unknown>
236236
)
237237

238-
// Log error
239-
getLogger().error(error)
238+
if (process.env.NODE_ENV !== 'production') {
239+
getLogger().error(error)
240+
}
240241

241242
return Promise.resolve()
242243
.then(() =>

src/core/query.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,16 @@ export class Query<
367367
}
368368
}
369369

370+
if (
371+
process.env.NODE_ENV !== 'production' &&
372+
!Array.isArray(this.options.queryKey)
373+
) {
374+
getLogger().error(
375+
'As of v4, queryKey needs to be an Array, but the queryKey used was:',
376+
JSON.stringify(this.options.queryKey)
377+
)
378+
}
379+
370380
const abortController = getAbortController()
371381

372382
// Create query function context
@@ -459,8 +469,9 @@ export class Query<
459469
// Notify cache callback
460470
this.cache.config.onError?.(error, this as Query<any, any, any, any>)
461471

462-
// Log error
463-
getLogger().error(error)
472+
if (process.env.NODE_ENV !== 'production') {
473+
getLogger().error(error)
474+
}
464475
}
465476

466477
if (!this.isFetchingOptimistic) {

src/core/queryObserver.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ export class QueryObserver<
7070
private previousQueryResult?: QueryObserverResult<TData, TError>
7171
private previousSelectError: TError | null
7272
private previousSelectFn?: (data: TQueryData) => TData
73-
private staleTimeoutId?: number
74-
private refetchIntervalId?: number
73+
private staleTimeoutId?: ReturnType<typeof setTimeout>
74+
private refetchIntervalId?: ReturnType<typeof setInterval>
7575
private currentRefetchInterval?: number | false
7676
private trackedProps!: Set<keyof QueryObserverResult>
7777

@@ -398,12 +398,12 @@ export class QueryObserver<
398398
}
399399

400400
private clearStaleTimeout(): void {
401-
clearTimeout(this.staleTimeoutId)
401+
clearTimeout(this.staleTimeoutId!)
402402
this.staleTimeoutId = undefined
403403
}
404404

405405
private clearRefetchInterval(): void {
406-
clearInterval(this.refetchIntervalId)
406+
clearInterval(this.refetchIntervalId!)
407407
this.refetchIntervalId = undefined
408408
}
409409

@@ -486,7 +486,9 @@ export class QueryObserver<
486486
}
487487
this.previousSelectError = null
488488
} catch (selectError) {
489-
getLogger().error(selectError)
489+
if (process.env.NODE_ENV !== 'production') {
490+
getLogger().error(selectError)
491+
}
490492
error = selectError as TError
491493
this.previousSelectError = selectError as TError
492494
errorUpdatedAt = Date.now()
@@ -529,7 +531,9 @@ export class QueryObserver<
529531
}
530532
this.previousSelectError = null
531533
} catch (selectError) {
532-
getLogger().error(selectError)
534+
if (process.env.NODE_ENV !== 'production') {
535+
getLogger().error(selectError)
536+
}
533537
error = selectError as TError
534538
this.previousSelectError = selectError as TError
535539
errorUpdatedAt = Date.now()

src/core/removable.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { isValidTimeout } from './utils'
22

33
export abstract class Removable {
44
cacheTime!: number
5-
private gcTimeout?: number
5+
private gcTimeout?: ReturnType<typeof setTimeout>
66

77
destroy(): void {
88
this.clearGcTimeout()
@@ -27,7 +27,7 @@ export abstract class Removable {
2727
}
2828

2929
protected clearGcTimeout() {
30-
clearTimeout(this.gcTimeout)
30+
clearTimeout(this.gcTimeout!)
3131
this.gcTimeout = undefined
3232
}
3333

src/core/tests/queriesObserver.test.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {
55
QueriesObserver,
66
QueryObserverResult,
77
QueryObserver,
8+
Logger,
9+
setLogger,
810
} from '../..'
911
import { QueryKey } from '..'
1012

@@ -39,6 +41,14 @@ describe('queriesObserver', () => {
3941
})
4042

4143
test('should still return value for undefined query key', async () => {
44+
const logger: Logger = {
45+
error: jest.fn(),
46+
log: jest.fn(),
47+
warn: jest.fn(),
48+
}
49+
50+
setLogger(logger)
51+
4252
const key1 = queryKey()
4353
const queryFn1 = jest.fn().mockReturnValue(1)
4454
const queryFn2 = jest.fn().mockReturnValue(2)
@@ -53,6 +63,9 @@ describe('queriesObserver', () => {
5363
await sleep(1)
5464
unsubscribe()
5565
expect(observerResult).toMatchObject([{ data: 1 }, { data: 2 }])
66+
67+
expect(logger.error).toHaveBeenCalledTimes(1)
68+
setLogger(console)
5669
})
5770

5871
test('should update when a query updates', async () => {

src/core/tests/utils.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ describe('core/utils', () => {
379379
// Do no throw an uncaught exception that cannot be tested with
380380
// this jest version
381381
}
382-
return 0
382+
return 0 as any
383383
})
384384
scheduleMicrotask(callback)
385385
jest.runAllTimers()

src/createAsyncStoragePersister/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function asyncThrottle<Args extends readonly unknown[], Result>(
5858
if (typeof func !== 'function') throw new Error('argument is not function.')
5959
const running = { current: false }
6060
let lastTime = 0
61-
let timeout: number
61+
let timeout: ReturnType<typeof setTimeout>
6262
const queue: Array<Args> = []
6363
return (...args: Args) =>
6464
(async () => {

src/createWebStoragePersister/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ function throttle<TArgs extends any[]>(
9696
func: (...args: TArgs) => any,
9797
wait = 100
9898
) {
99-
let timer: number | null = null
99+
let timer: ReturnType<typeof setTimeout> | null = null
100100
let params: TArgs
101101
return function (...args: TArgs) {
102102
params = args

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"noUncheckedIndexedAccess": true,
1515
"skipLibCheck": true,
1616
"strict": true,
17-
"types": ["jest"],
17+
"types": ["jest", "node"],
1818
"paths": {
1919
"react-query": ["./src/index.ts"]
2020
}

0 commit comments

Comments
 (0)