@tanstack/solid-query 4.10.3 → 4.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/solid-query",
3
- "version": "4.10.3",
3
+ "version": "4.11.1",
4
4
  "description": "Primitives for managing, caching and syncing asynchronous and remote data in Solid",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@
40
40
  "@tanstack/query-core": "4.10.3"
41
41
  },
42
42
  "peerDependencies": {
43
- "solid-js": "^1.5.4"
43
+ "solid-js": "^1.5.7"
44
44
  },
45
45
  "peerDependenciesMeta": {},
46
46
  "scripts": {
@@ -1386,7 +1386,7 @@ describe('createQuery', () => {
1386
1386
 
1387
1387
  it('should create a new query when refetching a removed query', async () => {
1388
1388
  const key = queryKey()
1389
- const states: Partial<CreateQueryResult<number>>[] = []
1389
+ const states: CreateQueryResult<number>[] = []
1390
1390
  let count = 0
1391
1391
 
1392
1392
  function Page() {
@@ -1400,7 +1400,7 @@ describe('createQuery', () => {
1400
1400
  )
1401
1401
 
1402
1402
  createRenderEffect(() => {
1403
- states.push({ data: state.data, dataUpdatedAt: state.dataUpdatedAt })
1403
+ states.push({ ...state })
1404
1404
  })
1405
1405
 
1406
1406
  return (
@@ -1510,7 +1510,7 @@ describe('createQuery', () => {
1510
1510
 
1511
1511
  it('should use query function from hook when the existing query does not have a query function', async () => {
1512
1512
  const key = queryKey()
1513
- const results: Partial<CreateQueryResult<string>>[] = []
1513
+ const results: CreateQueryResult<string>[] = []
1514
1514
 
1515
1515
  queryClient.setQueryData(key(), 'set')
1516
1516
 
@@ -1528,7 +1528,7 @@ describe('createQuery', () => {
1528
1528
  )
1529
1529
 
1530
1530
  createRenderEffect(() => {
1531
- results.push({ data: result.data, isFetching: result.isFetching })
1531
+ results.push({ ...result })
1532
1532
  })
1533
1533
 
1534
1534
  return (
@@ -1725,7 +1725,7 @@ describe('createQuery', () => {
1725
1725
 
1726
1726
  it('should not fetch when switching to a disabled query', async () => {
1727
1727
  const key = queryKey()
1728
- const states: Partial<CreateQueryResult<number>>[] = []
1728
+ const states: CreateQueryResult<number>[] = []
1729
1729
 
1730
1730
  function Page() {
1731
1731
  const [count, setCount] = createSignal(0)
@@ -1744,12 +1744,7 @@ describe('createQuery', () => {
1744
1744
  )
1745
1745
 
1746
1746
  createRenderEffect(() => {
1747
- const { data, isSuccess, isFetching } = state
1748
- states.push({
1749
- data,
1750
- isFetching,
1751
- isSuccess,
1752
- })
1747
+ states.push({ ...state })
1753
1748
  })
1754
1749
 
1755
1750
  createEffect(() => {
@@ -1793,7 +1788,7 @@ describe('createQuery', () => {
1793
1788
 
1794
1789
  it('should keep the previous data when keepPreviousData is set', async () => {
1795
1790
  const key = queryKey()
1796
- const states: Partial<CreateQueryResult<number>>[] = []
1791
+ const states: CreateQueryResult<number>[] = []
1797
1792
 
1798
1793
  function Page() {
1799
1794
  const [count, setCount] = createSignal(0)
@@ -1808,13 +1803,7 @@ describe('createQuery', () => {
1808
1803
  )
1809
1804
 
1810
1805
  createRenderEffect(() => {
1811
- const { data, isFetching, isSuccess, isPreviousData } = state
1812
- states.push({
1813
- data,
1814
- isFetching,
1815
- isSuccess,
1816
- isPreviousData,
1817
- })
1806
+ states.push({ ...state })
1818
1807
  })
1819
1808
 
1820
1809
  createEffect(() => {
@@ -2137,7 +2126,7 @@ describe('createQuery', () => {
2137
2126
 
2138
2127
  it('should keep the previous data on disabled query when keepPreviousData is set and switching query key multiple times', async () => {
2139
2128
  const key = queryKey()
2140
- const states: Partial<CreateQueryResult<number>>[] = []
2129
+ const states: CreateQueryResult<number>[] = []
2141
2130
 
2142
2131
  queryClient.setQueryData([key(), 10], 10)
2143
2132
 
@@ -2156,8 +2145,7 @@ describe('createQuery', () => {
2156
2145
  )
2157
2146
 
2158
2147
  createRenderEffect(() => {
2159
- const { data, isFetching, isSuccess, isPreviousData } = state
2160
- states.push({ data, isFetching, isSuccess, isPreviousData })
2148
+ states.push({ ...state })
2161
2149
  })
2162
2150
 
2163
2151
  createEffect(() => {
@@ -2780,7 +2768,7 @@ describe('createQuery', () => {
2780
2768
  const key = queryKey()
2781
2769
  const variables = { number: 5, boolean: false, object: {}, array: [] }
2782
2770
  type CustomQueryKey = readonly [ReturnType<typeof key>, typeof variables]
2783
- const states: Partial<CreateQueryResult<CustomQueryKey>>[] = []
2771
+ const states: CreateQueryResult<CustomQueryKey>[] = []
2784
2772
 
2785
2773
  // TODO(lukemurray): extract the query function to a variable queryFn
2786
2774
 
@@ -5087,7 +5075,7 @@ describe('createQuery', () => {
5087
5075
 
5088
5076
  it('should update query state and refetch when reset with resetQueries', async () => {
5089
5077
  const key = queryKey()
5090
- const states: Optional<Partial<CreateQueryResult<number>>>[] = []
5078
+ const states: CreateQueryResult<number>[] = []
5091
5079
  let count = 0
5092
5080
 
5093
5081
  function Page() {
@@ -5102,15 +5090,7 @@ describe('createQuery', () => {
5102
5090
  )
5103
5091
 
5104
5092
  createRenderEffect(() => {
5105
- const { data, isLoading, isFetching, isSuccess, isStale } = state
5106
-
5107
- states.push({
5108
- data,
5109
- isLoading,
5110
- isFetching,
5111
- isSuccess,
5112
- isStale,
5113
- })
5093
+ states.push({ ...state })
5114
5094
  })
5115
5095
 
5116
5096
  return (
@@ -5169,7 +5149,7 @@ describe('createQuery', () => {
5169
5149
 
5170
5150
  it('should update query state and not refetch when resetting a disabled query with resetQueries', async () => {
5171
5151
  const key = queryKey()
5172
- const states: Partial<CreateQueryResult<number>>[] = []
5152
+ const states: CreateQueryResult<number>[] = []
5173
5153
  let count = 0
5174
5154
 
5175
5155
  function Page() {
@@ -5184,14 +5164,7 @@ describe('createQuery', () => {
5184
5164
  )
5185
5165
 
5186
5166
  createRenderEffect(() => {
5187
- const { data, isLoading, isFetching, isSuccess, isStale } = state
5188
- states.push({
5189
- data,
5190
- isLoading,
5191
- isFetching,
5192
- isSuccess,
5193
- isStale,
5194
- })
5167
+ states.push({ ...state })
5195
5168
  })
5196
5169
 
5197
5170
  const { refetch } = state
@@ -805,52 +805,6 @@ describe("useQuery's in Suspense mode", () => {
805
805
  expect(queryFn).toHaveBeenCalledTimes(1)
806
806
  })
807
807
 
808
- it('should not render suspense fallback when not enabled', async () => {
809
- const key = queryKey()
810
-
811
- function Page() {
812
- const [enabled, setEnabled] = createSignal(false)
813
- const result = createQuery(
814
- key,
815
- () => {
816
- sleep(10)
817
- return 'data'
818
- },
819
- {
820
- suspense: true,
821
- get enabled() {
822
- return enabled()
823
- },
824
- },
825
- )
826
-
827
- return (
828
- <div>
829
- <button onClick={() => setEnabled(true)}>fire</button>
830
- <h1>{result.data ?? 'default'}</h1>
831
- </div>
832
- )
833
- }
834
-
835
- render(() => (
836
- <QueryClientProvider client={queryClient}>
837
- <Suspense fallback="Loading...">
838
- <Page />
839
- </Suspense>
840
- </QueryClientProvider>
841
- ))
842
-
843
- expect(screen.queryByText('Loading...')).toBeNull()
844
- expect(screen.getByRole('heading').textContent).toBe('default')
845
- await sleep(5)
846
- fireEvent.click(screen.getByRole('button', { name: /fire/i }))
847
- await waitFor(() => screen.getByText('Loading...'))
848
-
849
- await waitFor(() => {
850
- expect(screen.getByRole('heading').textContent).toBe('data')
851
- })
852
- })
853
-
854
808
  it('should error catched in error boundary without infinite loop', async () => {
855
809
  const key = queryKey()
856
810
 
@@ -0,0 +1,58 @@
1
+ import { fireEvent, render, screen, waitFor } from 'solid-testing-library'
2
+
3
+ import { createSignal, Show, startTransition, Suspense } from 'solid-js'
4
+ import { createQuery, QueryCache, QueryClientProvider } from '..'
5
+ import { createQueryClient, queryKey, sleep } from './utils'
6
+
7
+ describe("useQuery's in Suspense mode with transitions", () => {
8
+ const queryCache = new QueryCache()
9
+ const queryClient = createQueryClient({ queryCache })
10
+
11
+ it('should render the content when the transition is done', async () => {
12
+ const key = queryKey()
13
+
14
+ function Suspended() {
15
+ const state = createQuery(key, async () => {
16
+ await sleep(10)
17
+ return true
18
+ })
19
+
20
+ return <Show when={state.data}>Message</Show>
21
+ }
22
+
23
+ function Page() {
24
+ const [showSignal, setShowSignal] = createSignal(false)
25
+
26
+ return (
27
+ <div>
28
+ <button
29
+ aria-label="toggle"
30
+ onClick={() =>
31
+ startTransition(() => setShowSignal((value) => !value))
32
+ }
33
+ >
34
+ {showSignal() ? 'Hide' : 'Show'}
35
+ </button>
36
+ <Suspense fallback="Loading">
37
+ <Show when={showSignal()}>
38
+ <Suspended />
39
+ </Show>
40
+ </Suspense>
41
+ </div>
42
+ )
43
+ }
44
+
45
+ render(() => (
46
+ <QueryClientProvider client={queryClient}>
47
+ <Page />
48
+ </QueryClientProvider>
49
+ ))
50
+
51
+ await waitFor(() => screen.getByText('Show'))
52
+ fireEvent.click(screen.getByLabelText('toggle'))
53
+
54
+ await waitFor(() => screen.getByText('Message'))
55
+ // verify that the button also updated. See https://github.com/solidjs/solid/issues/1249
56
+ await waitFor(() => screen.getByText('Hide'))
57
+ })
58
+ })
@@ -31,7 +31,7 @@ export function createBaseQuery<
31
31
  Observer: typeof QueryObserver,
32
32
  ): QueryObserverResult<TData, TError> {
33
33
  const queryClient = useQueryClient({ context: options.context })
34
-
34
+ const emptyData = Symbol('empty')
35
35
  const defaultedOptions = queryClient.defaultQueryOptions(options)
36
36
  defaultedOptions._optimisticResults = 'optimistic'
37
37
  const observer = new Observer(queryClient, defaultedOptions)
@@ -45,6 +45,9 @@ export function createBaseQuery<
45
45
  () => {
46
46
  return new Promise((resolve) => {
47
47
  if (!(state.isFetching && state.isLoading)) {
48
+ if (unwrap(state.data) === emptyData) {
49
+ resolve(undefined)
50
+ }
48
51
  resolve(unwrap(state.data))
49
52
  }
50
53
  })
@@ -61,7 +64,15 @@ export function createBaseQuery<
61
64
  const unsubscribe = observer.subscribe((result) => {
62
65
  taskQueue.push(() => {
63
66
  batch(() => {
64
- setState(unwrap(result))
67
+ const unwrappedResult = { ...unwrap(result) }
68
+ if (unwrappedResult.data === undefined) {
69
+ // This is a hack to prevent Solid
70
+ // from deleting the data property when it is `undefined`
71
+ // ref: https://www.solidjs.com/docs/latest/api#updating-stores
72
+ // @ts-ignore
73
+ unwrappedResult.data = emptyData
74
+ }
75
+ setState(unwrap(unwrappedResult))
65
76
  mutate(() => unwrap(result.data))
66
77
  refetch()
67
78
  })
@@ -110,7 +121,7 @@ export function createBaseQuery<
110
121
  target: QueryObserverResult<TData, TError>,
111
122
  prop: keyof QueryObserverResult<TData, TError>,
112
123
  ): any {
113
- if (prop === 'data' && target.isLoading && target.isFetching) {
124
+ if (prop === 'data') {
114
125
  return dataResource()
115
126
  }
116
127
  return Reflect.get(target, prop)