Skip to content

Commit

Permalink
feat(solid-query): Add reconcile option
Browse files Browse the repository at this point in the history
  • Loading branch information
ardeora committed Apr 20, 2023
1 parent 0b0b706 commit dc81d2a
Show file tree
Hide file tree
Showing 15 changed files with 224 additions and 41 deletions.
84 changes: 84 additions & 0 deletions packages/solid-query/src/QueryClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import type {
QueryClientConfig as QueryCoreClientConfig,
DefaultOptions as CoreDefaultOptions,
QueryObserverOptions as QueryCoreObserverOptions,
InfiniteQueryObserverOptions as QueryCoreInfiniteQueryObserverOptions,
DefaultError,
QueryKey,
} from '@tanstack/query-core'
import { QueryClient as QueryCoreClient } from '@tanstack/query-core'

export interface QueryObserverOptions<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = never,
> extends Omit<
QueryCoreObserverOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey,
TPageParam
>,
'structuralSharing'
> {
/**
* Set this to a reconciliation key to enable reconciliation between query results.
* Set this to `false` to disable reconciliation between query results.
* Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom reconciliation logic.
* Defaults reconciliation key to `id`.
*/
reconcile?:
| string
| false
| ((oldData: TData | undefined, newData: TData) => TData)
}

export interface InfiniteQueryObserverOptions<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = unknown,
> extends Omit<
QueryCoreInfiniteQueryObserverOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey,
TPageParam
>,
'structuralSharing'
> {
/**
* Set this to a reconciliation key to enable reconciliation between query results.
* Set this to `false` to disable reconciliation between query results.
* Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom reconciliation logic.
* Defaults reconciliation key to `id`.
*/
reconcile?:
| string
| false
| ((oldData: TData | undefined, newData: TData) => TData)
}

export interface DefaultOptions<TError = DefaultError>
extends CoreDefaultOptions<TError> {
queries?: QueryObserverOptions<unknown, TError>
}

export interface QueryClientConfig extends QueryCoreClientConfig {
defaultOptions?: DefaultOptions
}

export class QueryClient extends QueryCoreClient {
constructor(config: QueryClientConfig = {}) {
super(config)
}
}
2 changes: 1 addition & 1 deletion packages/solid-query/src/QueryClientProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { QueryClient } from '@tanstack/query-core'
import type { QueryClient } from './QueryClient'
import type { JSX } from 'solid-js'
import { createContext, useContext, onMount, onCleanup } from 'solid-js'

Expand Down
91 changes: 75 additions & 16 deletions packages/solid-query/src/__tests__/createInfiniteQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Index,
Match,
Switch,
on,
} from 'solid-js'
import type {
CreateInfiniteQueryResult,
Expand Down Expand Up @@ -193,7 +194,8 @@ describe('useInfiniteQuery', () => {

it('should keep the previous data when placeholderData is set', async () => {
const key = queryKey()
const states: CreateInfiniteQueryResult<InfiniteData<string>>[] = []
const states: Partial<CreateInfiniteQueryResult<InfiniteData<string>>>[] =
[]

function Page() {
const [order, setOrder] = createSignal('desc')
Expand All @@ -212,7 +214,16 @@ describe('useInfiniteQuery', () => {
}))

createRenderEffect(() => {
states.push({ ...state })
states.push({
data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,
hasNextPage: state.hasNextPage,
hasPreviousPage: state.hasPreviousPage,
isFetching: state.isFetching,
isFetchingNextPage: state.isFetchingNextPage,
isFetchingPreviousPage: state.isFetchingPreviousPage,
isSuccess: state.isSuccess,
isPlaceholderData: state.isPlaceholderData,
})
})

return (
Expand Down Expand Up @@ -375,7 +386,8 @@ describe('useInfiniteQuery', () => {

it('should be able to reverse the data', async () => {
const key = queryKey()
const states: CreateInfiniteQueryResult<InfiniteData<number>>[] = []
const states: Partial<CreateInfiniteQueryResult<InfiniteData<number>>>[] =
[]

function Page() {
const state = createInfiniteQuery(() => ({
Expand All @@ -394,9 +406,19 @@ describe('useInfiniteQuery', () => {
defaultPageParam: 0,
}))

createRenderEffect(() => {
states.push({ ...state })
})
createRenderEffect(
on(
() => ({ ...state }),
() => {
states.push({
data: state.data
? JSON.parse(JSON.stringify(state.data))
: undefined,
isSuccess: state.isSuccess,
})
},
),
)

return (
<div>
Expand Down Expand Up @@ -439,7 +461,8 @@ describe('useInfiniteQuery', () => {

it('should be able to fetch a previous page', async () => {
const key = queryKey()
const states: CreateInfiniteQueryResult<InfiniteData<number>>[] = []
const states: Partial<CreateInfiniteQueryResult<InfiniteData<number>>>[] =
[]

function Page() {
const start = 10
Expand All @@ -456,7 +479,15 @@ describe('useInfiniteQuery', () => {
}))

createRenderEffect(() => {
states.push({ ...state })
states.push({
data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,
hasNextPage: state.hasNextPage,
hasPreviousPage: state.hasPreviousPage,
isFetching: state.isFetching,
isFetchingNextPage: state.isFetchingNextPage,
isFetchingPreviousPage: state.isFetchingPreviousPage,
isSuccess: state.isSuccess,
})
})

createEffect(() => {
Expand Down Expand Up @@ -518,7 +549,8 @@ describe('useInfiniteQuery', () => {

it('should be able to refetch when providing page params automatically', async () => {
const key = queryKey()
const states: CreateInfiniteQueryResult<InfiniteData<number>>[] = []
const states: Partial<CreateInfiniteQueryResult<InfiniteData<number>>>[] =
[]

function Page() {
const state = createInfiniteQuery(() => ({
Expand All @@ -535,7 +567,13 @@ describe('useInfiniteQuery', () => {
}))

createRenderEffect(() => {
states.push({ ...state })
states.push({
data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,
isFetching: state.isFetching,
isFetchingNextPage: state.isFetchingNextPage,
isRefetching: state.isRefetching,
isFetchingPreviousPage: state.isFetchingPreviousPage,
})
})

return (
Expand Down Expand Up @@ -632,7 +670,8 @@ describe('useInfiniteQuery', () => {

it('should silently cancel any ongoing fetch when fetching more', async () => {
const key = queryKey()
const states: CreateInfiniteQueryResult<InfiniteData<number>>[] = []
const states: Partial<CreateInfiniteQueryResult<InfiniteData<number>>>[] =
[]

function Page() {
const start = 10
Expand All @@ -649,7 +688,13 @@ describe('useInfiniteQuery', () => {
}))

createRenderEffect(() => {
states.push({ ...state })
states.push({
hasNextPage: state.hasNextPage,
data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,
isFetching: state.isFetching,
isFetchingNextPage: state.isFetchingNextPage,
isSuccess: state.isSuccess,
})
})

createEffect(() => {
Expand Down Expand Up @@ -978,7 +1023,8 @@ describe('useInfiniteQuery', () => {

it('should be able to set new pages with the query client', async () => {
const key = queryKey()
const states: CreateInfiniteQueryResult<InfiniteData<number>>[] = []
const states: Partial<CreateInfiniteQueryResult<InfiniteData<number>>>[] =
[]

function Page() {
const [firstPage, setFirstPage] = createSignal(0)
Expand All @@ -996,7 +1042,13 @@ describe('useInfiniteQuery', () => {
}))

createRenderEffect(() => {
states.push({ ...state })
states.push({
hasNextPage: state.hasNextPage,
data: state.data ? JSON.parse(JSON.stringify(state.data)) : undefined,
isFetching: state.isFetching,
isFetchingNextPage: state.isFetchingNextPage,
isSuccess: state.isSuccess,
})
})

createEffect(() => {
Expand Down Expand Up @@ -1066,7 +1118,8 @@ describe('useInfiniteQuery', () => {

it('should only refetch the first page when initialData is provided', async () => {
const key = queryKey()
const states: CreateInfiniteQueryResult<InfiniteData<number>>[] = []
const states: Partial<CreateInfiniteQueryResult<InfiniteData<number>>>[] =
[]

function Page() {
const state = createInfiniteQuery(() => ({
Expand All @@ -1083,7 +1136,13 @@ describe('useInfiniteQuery', () => {
}))

createRenderEffect(() => {
states.push({ ...state })
states.push({
data: JSON.parse(JSON.stringify(state.data)),
hasNextPage: state.hasNextPage,
isFetching: state.isFetching,
isFetchingNextPage: state.isFetchingNextPage,
isSuccess: state.isSuccess,
})
})

createEffect(() => {
Expand Down
7 changes: 3 additions & 4 deletions packages/solid-query/src/__tests__/createQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1282,7 +1282,6 @@ describe('createQuery', () => {
count++
return count === 1 ? result1 : result2
},
notifyOnChangeProps: 'all',
}))

createRenderEffect(() => {
Expand Down Expand Up @@ -1322,9 +1321,8 @@ describe('createQuery', () => {

expect(todos).toEqual(result1)
expect(newTodos).toEqual(result2)
expect(newTodos).not.toBe(todos)
expect(newTodo1).toBe(todo1)
expect(newTodo2).not.toBe(todo2)
expect(newTodo2).toBe(todo2)

return null
})
Expand Down Expand Up @@ -3257,7 +3255,7 @@ describe('createQuery', () => {

it('should keep initial data when the query key changes', async () => {
const key = queryKey()
const states: DefinedCreateQueryResult<{ count: number }>[] = []
const states: Partial<DefinedCreateQueryResult<{ count: number }>>[] = []

function Page() {
const [count, setCount] = createSignal(0)
Expand All @@ -3266,6 +3264,7 @@ describe('createQuery', () => {
queryFn: () => ({ count: 10 }),
staleTime: Infinity,
initialData: () => ({ count: count() }),
reconcile: false,
}))
createRenderEffect(() => {
states.push({ ...state })
Expand Down
2 changes: 1 addition & 1 deletion packages/solid-query/src/__tests__/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { QueryClientConfig } from '@tanstack/query-core'
import { QueryClient } from '@tanstack/query-core'
import { QueryClient } from '../QueryClient'
import type { ParentProps } from 'solid-js'
import { createEffect, createSignal, onCleanup, Show } from 'solid-js'
import { vi } from 'vitest'
Expand Down
Loading

0 comments on commit dc81d2a

Please sign in to comment.