Skip to content

Commit

Permalink
fix: make sure isDataEqual option is respected everywhere where we us…
Browse files Browse the repository at this point in the history
…e structuralSharing
  • Loading branch information
TkDodo committed May 25, 2022
1 parent 40b921a commit 17f20d4
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 26 deletions.
22 changes: 6 additions & 16 deletions src/core/query.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
getAbortController,
noop,
replaceEqualDeep,
timeUntilStale,
} from './utils'
import { getAbortController, noop, replaceData, timeUntilStale } from './utils'
import type {
InitialDataFunction,
QueryKey,
Expand Down Expand Up @@ -195,16 +190,11 @@ export class Query<
}
}

setData(data: TData, options?: SetDataOptions & { manual: boolean }): TData {
const prevData = this.state.data

// Use prev data if an isDataEqual function is defined and returns `true`
if (this.options.isDataEqual?.(prevData, data)) {
data = prevData as TData
} else if (this.options.structuralSharing !== false) {
// Structurally share data between prev and new data if needed
data = replaceEqualDeep(prevData, data)
}
setData(
newData: TData,
options?: SetDataOptions & { manual: boolean }
): TData {
const data = replaceData(this.state.data, newData, this.options)

// Set data and mark it as cached
this.dispatch({
Expand Down
17 changes: 7 additions & 10 deletions src/core/queryObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
isServer,
isValidTimeout,
noop,
replaceEqualDeep,
replaceData,
shallowEqualObjects,
timeUntilStale,
} from './utils'
Expand Down Expand Up @@ -467,9 +467,7 @@ export class QueryObserver<
try {
this.selectFn = options.select
data = options.select(state.data)
if (options.structuralSharing !== false) {
data = replaceEqualDeep(prevResult?.data, data)
}
data = replaceData(prevResult?.data, data, options)
this.selectResult = data
this.selectError = null
} catch (selectError) {
Expand Down Expand Up @@ -507,12 +505,11 @@ export class QueryObserver<
if (options.select && typeof placeholderData !== 'undefined') {
try {
placeholderData = options.select(placeholderData)
if (options.structuralSharing !== false) {
placeholderData = replaceEqualDeep(
prevResult?.data,
placeholderData
)
}
placeholderData = replaceData(
prevResult?.data,
placeholderData,
options
)
this.selectError = null
} catch (selectError) {
if (process.env.NODE_ENV !== 'production') {
Expand Down
29 changes: 29 additions & 0 deletions src/core/tests/queryObserver.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,35 @@ describe('queryObserver', () => {
unsubscribe()
})

test('should prefer isDataEqual to structuralSharing', async () => {
const key = queryKey()

const data = { value: 'data' }
const newData = { value: 'data' }

const observer = new QueryObserver(queryClient, {
queryKey: key,
queryFn: () => data,
})

const unsubscribe = observer.subscribe(() => undefined)

await sleep(10)
expect(observer.getCurrentResult().data).toBe(data)

observer.setOptions({
queryKey: key,
queryFn: () => newData,
isDataEqual: () => true,
structuralSharing: false,
})

await observer.refetch()
expect(observer.getCurrentResult().data).toBe(data)

unsubscribe()
})

test('select function error using placeholderdata should log an error', () => {
const key = queryKey()

Expand Down
14 changes: 14 additions & 0 deletions src/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,17 @@ export function getAbortController(): AbortController | undefined {
return new AbortController()
}
}

export function replaceData<
TData,
TOptions extends QueryOptions<any, any, any, any>
>(prevData: TData | undefined, data: TData, options: TOptions): TData {
// Use prev data if an isDataEqual function is defined and returns `true`
if (options.isDataEqual?.(prevData, data)) {
return prevData as TData
} else if (options.structuralSharing !== false) {
// Structurally share data between prev and new data if needed
return replaceEqualDeep(prevData, data)
}
return data
}

0 comments on commit 17f20d4

Please sign in to comment.