@tanstack/solid-query 5.0.5 → 5.2.0

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": "5.0.5",
3
+ "version": "5.2.0",
4
4
  "description": "Primitives for managing, caching and syncing asynchronous and remote data in Solid",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -0,0 +1,90 @@
1
+ import { describe, expect, expectTypeOf, it } from 'vitest'
2
+ import { fireEvent, render, waitFor } from '@solidjs/testing-library'
3
+ import { createEffect } from 'solid-js'
4
+ import { useMutationState } from '../useMutationState'
5
+ import { createMutation } from '../createMutation'
6
+ import { QueryClientProvider } from '../QueryClientProvider'
7
+ import { createQueryClient, doNotExecute, sleep } from './utils'
8
+ import type { MutationState, MutationStatus } from '@tanstack/query-core'
9
+
10
+ describe('useMutationState', () => {
11
+ describe('types', () => {
12
+ it('should default to QueryState', () => {
13
+ doNotExecute(() => {
14
+ const result = useMutationState(() => ({
15
+ filters: { status: 'pending' },
16
+ }))
17
+
18
+ expectTypeOf<Array<MutationState>>(result())
19
+ })
20
+ })
21
+ it('should infer with select', () => {
22
+ doNotExecute(() => {
23
+ const result = useMutationState(() => ({
24
+ filters: { status: 'pending' },
25
+ select: (mutation) => mutation.state.status,
26
+ }))
27
+
28
+ expectTypeOf<Array<MutationStatus>>(result())
29
+ })
30
+ })
31
+ })
32
+ it('should return variables after calling mutate', async () => {
33
+ const queryClient = createQueryClient()
34
+ const variables: Array<Array<unknown>> = []
35
+ const mutationKey = ['mutation']
36
+
37
+ function Variables() {
38
+ const states = useMutationState(() => ({
39
+ filters: { mutationKey, status: 'pending' },
40
+ select: (mutation) => mutation.state.variables,
41
+ }))
42
+
43
+ createEffect(() => {
44
+ variables.push(states())
45
+ })
46
+
47
+ return null
48
+ }
49
+
50
+ function Mutate() {
51
+ const mutation = createMutation(() => ({
52
+ mutationKey,
53
+ mutationFn: async (input: number) => {
54
+ await sleep(150)
55
+ return 'data' + input
56
+ },
57
+ }))
58
+
59
+ return (
60
+ <div>
61
+ data: {mutation.data ?? 'null'}
62
+ <button onClick={() => mutation.mutate(1)}>mutate</button>
63
+ </div>
64
+ )
65
+ }
66
+
67
+ function Page() {
68
+ return (
69
+ <div>
70
+ <Variables />
71
+ <Mutate />
72
+ </div>
73
+ )
74
+ }
75
+
76
+ const rendered = render(() => (
77
+ <QueryClientProvider client={queryClient}>
78
+ <Page />
79
+ </QueryClientProvider>
80
+ ))
81
+
82
+ await waitFor(() => rendered.getByText('data: null'))
83
+
84
+ fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))
85
+
86
+ await waitFor(() => rendered.getByText('data: data1'))
87
+
88
+ expect(variables).toEqual([[], [1], []])
89
+ })
90
+ })
@@ -66,3 +66,5 @@ export function setActTimeout(fn: () => void, ms?: number) {
66
66
  export function expectTypeNotAny<T>(_: 0 extends 1 & T ? never : T): void {
67
67
  return undefined
68
68
  }
69
+
70
+ export const doNotExecute = (_func: () => void) => true
@@ -0,0 +1,63 @@
1
+ import { createEffect, createMemo, createSignal, onCleanup } from 'solid-js'
2
+ import { replaceEqualDeep } from '@tanstack/query-core'
3
+ import { useQueryClient } from './QueryClientProvider'
4
+ import type {
5
+ DefaultError,
6
+ Mutation,
7
+ MutationCache,
8
+ MutationFilters,
9
+ MutationState,
10
+ } from '@tanstack/query-core'
11
+ import type { Accessor } from 'solid-js'
12
+ import type { QueryClient } from './QueryClient'
13
+
14
+ type MutationStateOptions<TResult = MutationState> = {
15
+ filters?: MutationFilters
16
+ select?: (
17
+ mutation: Mutation<unknown, DefaultError, unknown, unknown>,
18
+ ) => TResult
19
+ }
20
+
21
+ function getResult<TResult = MutationState>(
22
+ mutationCache: MutationCache,
23
+ options: MutationStateOptions<TResult>,
24
+ ): Array<TResult> {
25
+ return mutationCache
26
+ .findAll(options.filters)
27
+ .map(
28
+ (mutation): TResult =>
29
+ (options.select
30
+ ? options.select(
31
+ mutation as Mutation<unknown, DefaultError, unknown, unknown>,
32
+ )
33
+ : mutation.state) as TResult,
34
+ )
35
+ }
36
+
37
+ export function useMutationState<TResult = MutationState>(
38
+ options: Accessor<MutationStateOptions<TResult>> = () => ({}),
39
+ queryClient?: Accessor<QueryClient>,
40
+ ): Accessor<Array<TResult>> {
41
+ const client = createMemo(() => useQueryClient(queryClient?.()))
42
+ const mutationCache = createMemo(() => client().getMutationCache())
43
+
44
+ const [result, setResult] = createSignal(
45
+ getResult(mutationCache(), options()),
46
+ )
47
+
48
+ createEffect(() => {
49
+ const unsubscribe = mutationCache().subscribe(() => {
50
+ const nextResult = replaceEqualDeep(
51
+ result(),
52
+ getResult(mutationCache(), options()),
53
+ )
54
+ if (result() !== nextResult) {
55
+ setResult(nextResult)
56
+ }
57
+ })
58
+
59
+ onCleanup(unsubscribe)
60
+ })
61
+
62
+ return result
63
+ }