Skip to content

Commit

Permalink
feat(*): add optional logger prop to QueryClient config (#3246)
Browse files Browse the repository at this point in the history
- remove setLogger
- add optional `logger` prop to QueryClientConfig
- add getLogger public method to QueryClient
- add optional `logger` prop to QueryConfig and MutationConfig
- add getDefaultLogger function which returns a default logger based on
environment, which is used by everything that takes an optional logger
in their config
- add createQueryClient test util function that uses a mock logger
- replace all `new QueryClient` calls with createQueryClient calls
- remove mockConsoleError and usages from tests, which are not necessary anymore

BREAKING CHANGE: remove setLogger
  • Loading branch information
anilanar committed Feb 26, 2022
1 parent fe98d53 commit 315f0cf
Show file tree
Hide file tree
Showing 49 changed files with 318 additions and 584 deletions.
10 changes: 5 additions & 5 deletions docs/src/manifests/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@
"path": "/guides/suspense",
"editUrl": "/guides/suspense.md"
},
{
"title": "Custom Logger",
"path": "/guides/custom-logger",
"editUrl": "/guides/custom-logger.md"
},
{
"title": "Testing",
"path": "/guides/testing",
Expand Down Expand Up @@ -444,11 +449,6 @@
"path": "/reference/onlineManager",
"editUrl": "/reference/onlineManager.md"
},
{
"title": "setLogger",
"path": "/reference/setLogger",
"editUrl": "/reference/setLogger.md"
},
{
"title": "hydration",
"path": "/reference/hydration",
Expand Down
22 changes: 22 additions & 0 deletions docs/src/pages/guides/custom-logger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
id: custom-logger
title: Custom Logger
---

If you want to change how information is logged by React Query, you can set a custom logger when creating a `QueryClient`.

```js
const queryClient = new QueryClient({
logger: {
log: (...args) => {
// Log debugging information
},
warn: (...args) => {
// Log warning
},
error: (...args) => {
// Log error
},
},
})
```
15 changes: 14 additions & 1 deletion docs/src/pages/guides/migrating-to-react-query-4.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,24 @@ Additionally, `query.setDefaultOptions` was removed because it was also unused.

Types now require using TypeScript v4.1 or greater

### Logging
### Logging in production

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.

### `setLogger` is removed

It was possible to change the logger globally by calling `setLogger`. In v4, that function is replaced with an optional field when creating a `QueryClient`.

```diff
- import { QueryClient, setLogger } from 'react-query';
+ import { QueryClient } from 'react-query';

- setLogger(customLogger)
- const queryClient = new QueryClient();
+ const queryClient = new QueryClient({ logger: customLogger })
```

### Undefined is an illegale cache value for successful queries

In order to make bailing out of updates possible by returning `undefined`, we had to make `undefined` an illegal cache value. This is in-line with other concepts of react-query, for example, returning `undefined` from the [initialData function](guides/initial-query-data#initial-data-function) will also _not_ set data.
Expand Down
20 changes: 11 additions & 9 deletions docs/src/pages/guides/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,18 @@ This will set the defaults for all queries in the component tree to "no retries"
## Turn off network error logging

When testing we want to suppress network errors being logged to the console.
To do this, we can use `react-query`'s `setLogger()` function.
To do this, we can pass a custom logger to `QueryClient`:

```ts
// as part of your test setup
import { setLogger } from 'react-query'

setLogger({
log: console.log,
warn: console.warn,
// ✅ no more errors on the console
error: () => {},
import { QueryClient } from 'react-query'

const queryClient = new QueryClient({
logger: {
log: console.log,
warn: console.warn,
// ✅ no more errors on the console for tests
error: process.env.NODE_ENV === 'test' ? () => {} : console.error,
},
})
```

Expand Down Expand Up @@ -181,6 +182,7 @@ expect(result.current.data.pages).toStrictEqual([
expectation.done();
```

## Further reading

For additional tips and an alternative setup using `mock-service-worker`, have a look at [Testing React Query](../community/tkdodos-blog#5-testing-react-query) from
Expand Down
14 changes: 13 additions & 1 deletion docs/src/pages/reference/QueryClient.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Its available methods are:
- [`queryClient.resetQueries`](#queryclientresetqueries)
- [`queryClient.isFetching`](#queryclientisfetching)
- [`queryClient.isMutating`](#queryclientismutating)
- [`queryClient.getLogger`](#queryclientgetlogger)
- [`queryClient.getDefaultOptions`](#queryclientgetdefaultoptions)
- [`queryClient.setDefaultOptions`](#queryclientsetdefaultoptions)
- [`queryClient.getQueryDefaults`](#queryclientgetquerydefaults)
Expand All @@ -57,6 +58,9 @@ Its available methods are:
- `mutationCache?: MutationCache`
- Optional
- The mutation cache this client is connected to.
- `logger?: Logger`
- Optional
- The logger this client uses to log debugging information, warnings and errors. If not set, `console` is the default logger.
- `defaultOptions?: DefaultOptions`
- Optional
- Define defaults for all queries and mutations using this queryClient.
Expand Down Expand Up @@ -203,7 +207,7 @@ This distinction is more a "convenience" for ts devs that know which structure w

## `queryClient.setQueryData`

`setQueryData` is a synchronous function that can be used to immediately update a query's cached data. If the query does not exist, it will be created. **If the query is not utilized by a query hook in the default `cacheTime` of 5 minutes, the query will be garbage collected**. To update multiple queries at once and match query keys partially, you need to use [`queryClient.setQueriesData`](#queryclientsetqueriesdata) instead.
`setQueryData` is a synchronous function that can be used to immediately update a query's cached data. If the query does not exist, it will be created. **If the query is not utilized by a query hook in the default `cacheTime` of 5 minutes, the query will be garbage collected**. To update multiple queries at once and match query keys partially, you need to use [`queryClient.setQueriesData`](#queryclientsetqueriesdata) instead.

> The difference between using `setQueryData` and `fetchQuery` is that `setQueryData` is sync and assumes that you already synchronously have the data available. If you need to fetch the data asynchronously, it's suggested that you either refetch the query key or use `fetchQuery` to handle the asynchronous fetch.
Expand Down Expand Up @@ -450,6 +454,14 @@ React Query also exports a handy [`useIsMutating`](./useIsMutating) hook that wi
**Returns**

This method returns the number of fetching mutations.
## `queryClient.getLogger`

The `getLogger` method returns the logger which have been set when creating the client.

```js
const logger = queryClient.getLogger()
```

## `queryClient.getDefaultOptions`

The `getDefaultOptions` method returns the default options which have been set when creating the client or with `setDefaultOptions`.
Expand Down
43 changes: 0 additions & 43 deletions docs/src/pages/reference/setLogger.md

This file was deleted.

1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ module.exports = {
moduleNameMapper: {
'react-query': '<rootDir>/src/index.ts',
},
clearMocks: true,
}
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@
"es/index.js",
"es/reactjs/index.js",
"es/reactjs/setBatchUpdatesFn.js",
"es/reactjs/setLogger.js",
"lib/index.js",
"lib/reactjs/index.js",
"lib/reactjs/setBatchUpdatesFn.js",
"lib/reactjs/setLogger.js"
"lib/reactjs/setBatchUpdatesFn.js"
],
"scripts": {
"test": "is-ci \"test:ci\" \"test:dev\"",
Expand Down
1 change: 0 additions & 1 deletion src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export { QueriesObserver } from './queriesObserver'
export { InfiniteQueryObserver } from './infiniteQueryObserver'
export { MutationCache } from './mutationCache'
export { MutationObserver } from './mutationObserver'
export { setLogger } from './logger'
export { notifyManager } from './notifyManager'
export { focusManager } from './focusManager'
export { onlineManager } from './onlineManager'
Expand Down
11 changes: 11 additions & 0 deletions src/core/logger.native.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { Logger } from './logger'

/**
* See https://github.com/tannerlinsley/react-query/issues/795
* and https://github.com/tannerlinsley/react-query/pull/3246/#discussion_r795105707
*/
export const defaultLogger: Logger = {
log: console.log,
warn: console.warn,
error: console.warn,
}
14 changes: 1 addition & 13 deletions src/core/logger.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// TYPES

export interface Logger {
log: LogFunction
warn: LogFunction
Expand All @@ -8,14 +6,4 @@ export interface Logger {

type LogFunction = (...args: any[]) => void

// FUNCTIONS

let logger: Logger = console

export function getLogger(): Logger {
return logger
}

export function setLogger(newLogger: Logger) {
logger = newLogger
}
export const defaultLogger: Logger = console
7 changes: 5 additions & 2 deletions src/core/mutation.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { MutationOptions, MutationStatus, MutationMeta } from './types'
import type { MutationCache } from './mutationCache'
import type { MutationObserver } from './mutationObserver'
import { getLogger } from './logger'
import { defaultLogger, Logger } from './logger'
import { notifyManager } from './notifyManager'
import { Removable } from './removable'
import { canFetch, Retryer, createRetryer } from './retryer'
Expand All @@ -12,6 +12,7 @@ interface MutationConfig<TData, TError, TVariables, TContext> {
mutationId: number
mutationCache: MutationCache
options: MutationOptions<TData, TError, TVariables, TContext>
logger?: Logger
defaultOptions?: MutationOptions<TData, TError, TVariables, TContext>
state?: MutationState<TData, TError, TVariables, TContext>
meta?: MutationMeta
Expand Down Expand Up @@ -89,6 +90,7 @@ export class Mutation<

private observers: MutationObserver<TData, TError, TVariables, TContext>[]
private mutationCache: MutationCache
private logger: Logger
private retryer?: Retryer<TData>

constructor(config: MutationConfig<TData, TError, TVariables, TContext>) {
Expand All @@ -100,6 +102,7 @@ export class Mutation<
}
this.mutationId = config.mutationId
this.mutationCache = config.mutationCache
this.logger = config.logger || defaultLogger
this.observers = []
this.state = config.state || getDefaultState()
this.meta = config.meta
Expand Down Expand Up @@ -252,7 +255,7 @@ export class Mutation<
)

if (process.env.NODE_ENV !== 'production') {
getLogger().error(error)
this.logger.error(error)
}

return Promise.resolve()
Expand Down
1 change: 1 addition & 0 deletions src/core/mutationCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export class MutationCache extends Subscribable<MutationCacheListener> {
): Mutation<TData, TError, TVariables, TContext> {
const mutation = new Mutation({
mutationCache: this,
logger: client.getLogger(),
mutationId: ++this.mutationId,
options: client.defaultMutationOptions(options),
state,
Expand Down
22 changes: 12 additions & 10 deletions src/core/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import type {
} from './types'
import type { QueryCache } from './queryCache'
import type { QueryObserver } from './queryObserver'
import { defaultLogger, Logger } from './logger'
import { notifyManager } from './notifyManager'
import { getLogger } from './logger'
import { Retryer, isCancelledError, canFetch, createRetryer } from './retryer'
import { Removable } from './removable'

Expand All @@ -33,6 +33,7 @@ interface QueryConfig<
cache: QueryCache
queryKey: TQueryKey
queryHash: string
logger?: Logger
options?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
defaultOptions?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
state?: QueryState<TData, TError>
Expand Down Expand Up @@ -155,6 +156,7 @@ export class Query<
isFetchingOptimistic?: boolean

private cache: QueryCache
private logger: Logger
private promise?: Promise<TData>
private retryer?: Retryer<TData>
private observers: QueryObserver<any, any, any, any, any>[]
Expand All @@ -169,6 +171,7 @@ export class Query<
this.setOptions(config.options)
this.observers = []
this.cache = config.cache
this.logger = config.logger || defaultLogger
this.queryKey = config.queryKey
this.queryHash = config.queryHash
this.initialState = config.state || getDefaultState(this.options)
Expand Down Expand Up @@ -360,14 +363,13 @@ 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)
)
if (!Array.isArray(this.options.queryKey)) {
if (process.env.NODE_ENV !== 'production') {
this.logger.error(
'As of v4, queryKey needs to be an Array, but the queryKey used was:',
JSON.stringify(this.options.queryKey)
)
}
}

const abortController = getAbortController()
Expand Down Expand Up @@ -447,7 +449,7 @@ export class Query<
this.cache.config.onError?.(error, this as Query<any, any, any, any>)

if (process.env.NODE_ENV !== 'production') {
getLogger().error(error)
this.logger.error(error)
}
}

Expand Down
1 change: 1 addition & 0 deletions src/core/queryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export class QueryCache extends Subscribable<QueryCacheListener> {
if (!query) {
query = new Query({
cache: this,
logger: client.getLogger(),
queryKey,
queryHash,
options: client.defaultQueryOptions(options),
Expand Down

0 comments on commit 315f0cf

Please sign in to comment.