@umituz/react-native-tanstack 1.2.9 → 1.2.11
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": "@umituz/react-native-tanstack",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.11",
|
|
4
4
|
"description": "TanStack Query configuration and utilities for React Native apps - Pre-configured QueryClient with AsyncStorage persistence",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -3,37 +3,33 @@
|
|
|
3
3
|
* Presentation layer - Optimistic update helper
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { useMutation, useQueryClient
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Context type for optimistic updates
|
|
10
|
-
*/
|
|
11
|
-
interface OptimisticContext<TData> {
|
|
12
|
-
previousData: TData | undefined;
|
|
13
|
-
}
|
|
6
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
14
7
|
|
|
15
8
|
/**
|
|
16
9
|
* Optimistic update configuration
|
|
17
10
|
*/
|
|
18
|
-
export interface OptimisticUpdateConfig<TData, TVariables> {
|
|
11
|
+
export interface OptimisticUpdateConfig<TData, TVariables, TError = Error> {
|
|
19
12
|
queryKey: readonly unknown[];
|
|
20
13
|
updater: (oldData: TData | undefined, variables: TVariables) => TData;
|
|
21
14
|
invalidateOnSuccess?: boolean;
|
|
15
|
+
mutationFn: (variables: TVariables) => Promise<TData>;
|
|
16
|
+
onError?: (error: TError, variables: TVariables, context: unknown) => void;
|
|
17
|
+
onSettled?: (data: TData | undefined, error: TError | null, variables: TVariables, context: unknown) => void;
|
|
18
|
+
onSuccess?: (data: TData, variables: TVariables, context: unknown) => void;
|
|
22
19
|
}
|
|
23
20
|
|
|
24
21
|
/**
|
|
25
22
|
* Hook for mutations with optimistic updates and automatic rollback
|
|
26
23
|
*/
|
|
27
24
|
export function useOptimisticUpdate<TData = unknown, TVariables = unknown, TError = Error>(
|
|
28
|
-
config: OptimisticUpdateConfig<TData, TVariables
|
|
29
|
-
Omit<UseMutationOptions<TData, TError, TVariables, OptimisticContext<TData>>, 'onMutate'>,
|
|
25
|
+
config: OptimisticUpdateConfig<TData, TVariables, TError>,
|
|
30
26
|
) {
|
|
31
27
|
const queryClient = useQueryClient();
|
|
32
|
-
const { queryKey, updater, invalidateOnSuccess = true, onError, onSettled,
|
|
28
|
+
const { queryKey, updater, invalidateOnSuccess = true, onError, onSettled, onSuccess, mutationFn } = config;
|
|
33
29
|
|
|
34
|
-
return useMutation
|
|
35
|
-
|
|
36
|
-
onMutate: async (variables) => {
|
|
30
|
+
return useMutation({
|
|
31
|
+
mutationFn,
|
|
32
|
+
onMutate: async (variables: TVariables) => {
|
|
37
33
|
await queryClient.cancelQueries({ queryKey });
|
|
38
34
|
const previousData = queryClient.getQueryData<TData>(queryKey);
|
|
39
35
|
|
|
@@ -49,9 +45,11 @@ export function useOptimisticUpdate<TData = unknown, TVariables = unknown, TErro
|
|
|
49
45
|
|
|
50
46
|
return { previousData };
|
|
51
47
|
},
|
|
52
|
-
onError: (error, variables, context) => {
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
onError: (error: TError, variables: TVariables, context: unknown) => {
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
|
+
const ctx = context as any;
|
|
51
|
+
if (ctx?.previousData !== undefined) {
|
|
52
|
+
queryClient.setQueryData(queryKey, ctx.previousData);
|
|
55
53
|
|
|
56
54
|
if (__DEV__) {
|
|
57
55
|
// eslint-disable-next-line no-console
|
|
@@ -63,7 +61,12 @@ export function useOptimisticUpdate<TData = unknown, TVariables = unknown, TErro
|
|
|
63
61
|
onError(error, variables, context);
|
|
64
62
|
}
|
|
65
63
|
},
|
|
66
|
-
|
|
64
|
+
onSuccess: (data: TData, variables: TVariables, context: unknown) => {
|
|
65
|
+
if (onSuccess) {
|
|
66
|
+
onSuccess(data, variables, context);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
onSettled: (data: TData | undefined, error: TError | null, variables: TVariables, context: unknown) => {
|
|
67
70
|
if (invalidateOnSuccess && !error) {
|
|
68
71
|
queryClient.invalidateQueries({ queryKey });
|
|
69
72
|
}
|
|
@@ -79,8 +82,7 @@ export function useOptimisticUpdate<TData = unknown, TVariables = unknown, TErro
|
|
|
79
82
|
* Hook for list mutations with optimistic updates
|
|
80
83
|
*/
|
|
81
84
|
export function useOptimisticListUpdate<TData extends unknown[], TVariables = unknown>(
|
|
82
|
-
config: OptimisticUpdateConfig<TData, TVariables
|
|
83
|
-
Omit<UseMutationOptions<TData, Error, TVariables, OptimisticContext<TData>>, 'onMutate'>,
|
|
85
|
+
config: OptimisticUpdateConfig<TData, TVariables, Error>,
|
|
84
86
|
) {
|
|
85
|
-
return useOptimisticUpdate<TData, TVariables>(config);
|
|
87
|
+
return useOptimisticUpdate<TData, TVariables, Error>(config);
|
|
86
88
|
}
|
|
@@ -3,10 +3,7 @@
|
|
|
3
3
|
* Presentation layer - Pagination helper
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
useInfiniteQuery,
|
|
8
|
-
type UseInfiniteQueryOptions,
|
|
9
|
-
} from '@tanstack/react-query';
|
|
6
|
+
import { useInfiniteQuery } from '@tanstack/react-query';
|
|
10
7
|
import { useMemo } from 'react';
|
|
11
8
|
|
|
12
9
|
/**
|
|
@@ -44,31 +41,31 @@ export interface OffsetPaginatedResponse<TData> {
|
|
|
44
41
|
limit: number;
|
|
45
42
|
}
|
|
46
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Cursor pagination options
|
|
46
|
+
*/
|
|
47
|
+
export interface CursorPaginationOptions<TData> {
|
|
48
|
+
queryKey: readonly unknown[];
|
|
49
|
+
queryFn: (context: { pageParam?: string }) => Promise<CursorPaginatedResponse<TData>>;
|
|
50
|
+
limit?: number;
|
|
51
|
+
enabled?: boolean;
|
|
52
|
+
staleTime?: number;
|
|
53
|
+
gcTime?: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
47
56
|
/**
|
|
48
57
|
* Hook for cursor-based infinite scroll
|
|
49
58
|
*/
|
|
50
|
-
export function useCursorPagination<TData>(
|
|
51
|
-
|
|
52
|
-
UseInfiniteQueryOptions<
|
|
53
|
-
CursorPaginatedResponse<TData>,
|
|
54
|
-
Error,
|
|
55
|
-
CursorPaginatedResponse<TData>,
|
|
56
|
-
CursorPaginatedResponse<TData>,
|
|
57
|
-
readonly unknown[],
|
|
58
|
-
string | undefined
|
|
59
|
-
>,
|
|
60
|
-
'getNextPageParam' | 'initialPageParam'
|
|
61
|
-
> & {
|
|
62
|
-
limit?: number;
|
|
63
|
-
},
|
|
64
|
-
) {
|
|
65
|
-
const { limit: _limit = 20, ...queryOptions } = options;
|
|
59
|
+
export function useCursorPagination<TData>(options: CursorPaginationOptions<TData>) {
|
|
60
|
+
const { queryKey, queryFn, limit: _limit = 20, ...restOptions } = options;
|
|
66
61
|
|
|
67
62
|
const result = useInfiniteQuery({
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
queryKey,
|
|
64
|
+
queryFn: ({ pageParam }) => queryFn({ pageParam }),
|
|
65
|
+
initialPageParam: undefined as string | undefined,
|
|
70
66
|
getNextPageParam: (lastPage: CursorPaginatedResponse<TData>) =>
|
|
71
67
|
lastPage.hasMore ? lastPage.nextCursor : undefined,
|
|
68
|
+
...restOptions,
|
|
72
69
|
});
|
|
73
70
|
|
|
74
71
|
const flatData = useMemo(() => {
|
|
@@ -83,33 +80,33 @@ export function useCursorPagination<TData>(
|
|
|
83
80
|
};
|
|
84
81
|
}
|
|
85
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Offset pagination options
|
|
85
|
+
*/
|
|
86
|
+
export interface OffsetPaginationOptions<TData> {
|
|
87
|
+
queryKey: readonly unknown[];
|
|
88
|
+
queryFn: (context: { pageParam: OffsetPageParam }) => Promise<OffsetPaginatedResponse<TData>>;
|
|
89
|
+
limit?: number;
|
|
90
|
+
enabled?: boolean;
|
|
91
|
+
staleTime?: number;
|
|
92
|
+
gcTime?: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
86
95
|
/**
|
|
87
96
|
* Hook for offset-based pagination
|
|
88
97
|
*/
|
|
89
|
-
export function useOffsetPagination<TData>(
|
|
90
|
-
options
|
|
91
|
-
UseInfiniteQueryOptions<
|
|
92
|
-
OffsetPaginatedResponse<TData>,
|
|
93
|
-
Error,
|
|
94
|
-
OffsetPaginatedResponse<TData>,
|
|
95
|
-
OffsetPaginatedResponse<TData>,
|
|
96
|
-
readonly unknown[],
|
|
97
|
-
OffsetPageParam
|
|
98
|
-
>,
|
|
99
|
-
'getNextPageParam' | 'initialPageParam'
|
|
100
|
-
> & {
|
|
101
|
-
limit?: number;
|
|
102
|
-
},
|
|
103
|
-
) {
|
|
104
|
-
const { limit = 20, ...queryOptions } = options;
|
|
98
|
+
export function useOffsetPagination<TData>(options: OffsetPaginationOptions<TData>) {
|
|
99
|
+
const { queryKey, queryFn, limit = 20, ...restOptions } = options;
|
|
105
100
|
|
|
106
101
|
const result = useInfiniteQuery({
|
|
107
|
-
|
|
102
|
+
queryKey,
|
|
103
|
+
queryFn: ({ pageParam }) => queryFn({ pageParam }),
|
|
108
104
|
initialPageParam: { offset: 0, limit },
|
|
109
105
|
getNextPageParam: (lastPage: OffsetPaginatedResponse<TData>) => {
|
|
110
106
|
const nextOffset = lastPage.offset + lastPage.limit;
|
|
111
107
|
return nextOffset < lastPage.total ? { offset: nextOffset, limit } : undefined;
|
|
112
108
|
},
|
|
109
|
+
...restOptions,
|
|
113
110
|
});
|
|
114
111
|
|
|
115
112
|
const flatData = useMemo(() => {
|