Skip to content

Commit

Permalink
fix(use-data-query): throw more specific error on serialization failure
Browse files Browse the repository at this point in the history
  • Loading branch information
ismay committed Aug 12, 2021
1 parent 93938cc commit 35a6b28
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 54 deletions.
40 changes: 0 additions & 40 deletions services/data/src/react/hooks/stableValueHash.test.ts

This file was deleted.

53 changes: 53 additions & 0 deletions services/data/src/react/hooks/stableVariablesHash.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { stableVariablesHash } from './stableVariablesHash'

describe('stableVariablesHash', () => {
it('sorts objects before hashing', () => {
const one = {
a: {
one: 1,
two: 2,
three: 3,
},
b: [1, 2, 3],
c: 'c',
}
const two = {
c: 'c',
b: [1, 2, 3],
a: {
three: 3,
two: 2,
one: 1,
},
}

expect(stableVariablesHash(one)).toEqual(stableVariablesHash(two))
})

it('can handle primitives', () => {
const one = undefined
const two = 'string'
const three = 3
const four = null
const five = true

expect(stableVariablesHash(one)).toMatchInlineSnapshot(`undefined`)
expect(stableVariablesHash(two)).toMatchInlineSnapshot(`"\\"string\\""`)
expect(stableVariablesHash(three)).toMatchInlineSnapshot(`"3"`)
expect(stableVariablesHash(four)).toMatchInlineSnapshot(`"null"`)
expect(stableVariablesHash(five)).toMatchInlineSnapshot(`"true"`)
})

it('throws a clear error when something goes wrong', () => {
const unserializable = {
value: 'value',
}
unserializable.circular = unserializable

expect(() =>
stableVariablesHash(unserializable)
).toThrowErrorMatchingInlineSnapshot(
`"Could not serialize variables. Make sure that the variables do not contain circular references and can be processed by JSON.stringify."`
)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,25 @@ export function isPlainObject(o: any): o is Object {
*/

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function stableValueHash(value: any): string {
return JSON.stringify(value, (_, val) =>
isPlainObject(val)
? Object.keys(val)
.sort()
.reduce((result, key) => {
result[key] = val[key]
return result
}, {} as any)
: val
)
export function stableVariablesHash(value: any): string {
let hash

try {
hash = JSON.stringify(value, (_, val) =>
isPlainObject(val)
? Object.keys(val)
.sort()
.reduce((result, key) => {
result[key] = val[key]
return result
}, {} as any)
: val
)
} catch (e) {
throw new Error(
'Could not serialize variables. Make sure that the variables do not contain circular references and can be processed by JSON.stringify.'
)
}

return hash
}
6 changes: 3 additions & 3 deletions services/data/src/react/hooks/useDataQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useQuery, setLogger } from 'react-query'
import { Query, QueryOptions } from '../../engine'
import { FetchError } from '../../engine/types/FetchError'
import { QueryRenderInput, QueryRefetchFunction } from '../../types'
import { stableValueHash } from './stableValueHash'
import { stableVariablesHash } from './stableVariablesHash'
import { useDataEngine } from './useDataEngine'
import { useStaticInput } from './useStaticInput'

Expand Down Expand Up @@ -107,10 +107,10 @@ export const useDataQuery = (
if (newVariables) {
// Use cached hash if it exists
const currentHash =
variablesHash.current || stableValueHash(variables)
variablesHash.current || stableVariablesHash(variables)

const mergedVariables = { ...variables, ...newVariables }
const mergedHash = stableValueHash(mergedVariables)
const mergedHash = stableVariablesHash(mergedVariables)
const identical = currentHash === mergedHash

if (identical) {
Expand Down

0 comments on commit 35a6b28

Please sign in to comment.