Skip to content

Commit b1ca0d2

Browse files
authored
fix: Handle console.log of null values in React Devtools (#909)
In some cases (can't reproduce it reliably though), turning on debug logs and logging console.log('%s', null) will throw an error. Falling back to the flattened message if the overloaded console.log fails. Should be fixed upstream by facebook/react#32372. Closes #808.
1 parent db36920 commit b1ca0d2

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

packages/nuqs/src/debug.test.ts

+32-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { describe, expect, test } from 'vitest'
1+
import { describe, expect, it } from 'vitest'
22
import { sprintf } from './debug'
33

44
describe('debug/sprintf', () => {
5-
test('%s', () => {
5+
it('formats strings with %s', () => {
66
expect(sprintf('%s', 'foo')).toBe('foo')
77
expect(sprintf('%s', 1)).toBe('1')
88
expect(sprintf('%s', true)).toBe('true')
@@ -11,7 +11,31 @@ describe('debug/sprintf', () => {
1111
expect(sprintf('%s', {})).toBe('[object Object]')
1212
expect(sprintf('%s', [])).toBe('')
1313
})
14-
test('%O', () => {
14+
it('formats integers with %d', () => {
15+
expect(sprintf('%d', 1)).toBe('1')
16+
expect(sprintf('%d', 1.5)).toBe('1.5')
17+
expect(sprintf('%d', '1')).toBe('1')
18+
expect(sprintf('%d', '1.5')).toBe('1.5')
19+
expect(sprintf('%d', true)).toBe('true')
20+
expect(sprintf('%d', false)).toBe('false')
21+
expect(sprintf('%d', null)).toBe('null')
22+
expect(sprintf('%d', undefined)).toBe('undefined')
23+
expect(sprintf('%d', {})).toBe('[object Object]')
24+
expect(sprintf('%d', [])).toBe('')
25+
})
26+
it('formats floats with %f', () => {
27+
expect(sprintf('%f', 1)).toBe('1')
28+
expect(sprintf('%f', 1.5)).toBe('1.5')
29+
expect(sprintf('%f', '1')).toBe('1')
30+
expect(sprintf('%f', '1.5')).toBe('1.5')
31+
expect(sprintf('%f', true)).toBe('true')
32+
expect(sprintf('%f', false)).toBe('false')
33+
expect(sprintf('%f', null)).toBe('null')
34+
expect(sprintf('%f', undefined)).toBe('undefined')
35+
expect(sprintf('%f', {})).toBe('[object Object]')
36+
expect(sprintf('%f', [])).toBe('')
37+
})
38+
it('formats objects with %O', () => {
1539
expect(sprintf('%O', 'foo')).toBe('"foo"')
1640
expect(sprintf('%O', 1)).toBe('1')
1741
expect(sprintf('%O', true)).toBe('true')
@@ -21,12 +45,16 @@ describe('debug/sprintf', () => {
2145
expect(sprintf('%O', [])).toBe('[]')
2246
expect(sprintf('%O', { hello: 'world' })).toBe('{hello:"world"}')
2347
})
24-
test('All together now', () => {
48+
it('formats multiple arguments', () => {
2549
expect(sprintf('%s %O', 'foo', { hello: 'world' })).toBe(
2650
'foo {hello:"world"}'
2751
)
2852
expect(sprintf('%O %s', { hello: 'world' }, 'foo')).toBe(
2953
'{hello:"world"} foo'
3054
)
3155
})
56+
it('supports mismatching numbers of arguments and placeholders', () => {
57+
expect(sprintf('%s %s', 'foo')).toBe('foo undefined')
58+
expect(sprintf('%s %s', 'foo', 'bar', 'baz')).toBe('foo bar')
59+
})
3260
})

packages/nuqs/src/debug.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ export function debug(message: string, ...args: any[]) {
66
}
77
const msg = sprintf(message, ...args)
88
performance.mark(msg)
9-
console.log(message, ...args)
9+
try {
10+
// Handle React Devtools not being able to console.log('%s', null)
11+
console.log(message, ...args)
12+
} catch (error) {
13+
console.log(msg)
14+
}
1015
}
1116

1217
export function warn(message: string, ...args: any[]) {

0 commit comments

Comments
 (0)