toss / suspensive

Packages to use React Suspense easily (one of Tanstack Query community resources)
https://suspensive.org
MIT License
417 stars 37 forks source link

[Feature]: infiniteQueryOptions #1015

Closed kangju2000 closed 1 day ago

kangju2000 commented 1 week ago

Package Scope

@suspensive/react-query-4

Bug description

I found a type error that occurs when passing the return value of queryOptions as a property to SuspenseInfiniteQuery.

Check it out here: Codesandbox Link

Expected behavior

The return value of queryOptions should be compatible with the props of SuspenseInfiniteQuery without causing any TypeScript errors.

To Reproduce

No response

Possible Solution

If queryOptions cannot adequately handle the infiniteQuery type, we might consider creating a separate infiniteQueryOptions as an alternative approach.

etc.

No response

manudeli commented 1 week ago

https://github.com/toss/suspensive/pull/1016#issuecomment-2198900615

gwansikk commented 1 week ago

@kangju2000 @manudeli

It looks like the error is occurring due to type mismatches in refetchOnMount, refetchOnReconnect, and refetchOnWindowFocus. The queryOptions are typed as data: TData, while in the Infinity Hook, data: InfiniteData<TData> should be used.

I agree with both of you that creating infiniteQueryOptions to address this is the perfect solution! If this task takes a long time, wrapping it as a temporary measure and gradually updating it could also be a good approach.

Here is a temporary solution that wraps queryOptions to ensure they become InfiniteQueryOptions

useSuspenseInfiniteQuery.ts

+ type RefetchOption<TQueryFnData, TError, TQueryData, TQueryKey extends QueryKey> =
+  | boolean
+  | 'always'
+  | ((query: Query<TQueryFnData, TError, TQueryData, TQueryKey>) => boolean | 'always')

export interface UseSuspenseInfiniteQueryOptions<
  TQueryFnData = unknown,
  TError = unknown,
  TData = TQueryFnData,
  TQueryKey extends QueryKey = QueryKey,
 > extends OmitKeyof<
    UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>,
    | 'suspense'
    | 'useErrorBoundary'
    | 'enabled'
    | 'placeholderData'
+    | 'refetchOnMount'
+    | 'refetchOnReconnect'
+    | 'refetchOnWindowFocus'
  > {
+  refetchOnMount?: RefetchOption<TQueryFnData, TError, TData, TQueryKey>
+  refetchOnReconnect?: RefetchOption<TQueryFnData, TError, TData, TQueryKey>
+  refetchOnWindowFocus?: RefetchOption<TQueryFnData, TError, TData, TQueryKey>
}

/**
 * This hook is wrapping useInfiniteQuery of `@tanstack/react-query` v4 with default suspense option.
 * @see {@link https://suspensive.org/docs/react-query/useSuspenseInfiniteQuery}
 */
export function useSuspenseInfiniteQuery<
  TQueryFnData = unknown,
  TError = unknown,
  TData = TQueryFnData,
  TQueryKey extends QueryKey = QueryKey,
>(
  options: UseSuspenseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey>
): UseSuspenseInfiniteQueryResult<TData, TError> {
  const { refetchOnMount, refetchOnReconnect, refetchOnWindowFocus, ...restOptions } = options
  return useInfiniteQuery({
    ...restOptions,
    enabled: true,
    suspense: true,
    useErrorBoundary: true,
+    refetchOnMount: refetchOnMount as UseInfiniteQueryOptions<
+      TQueryFnData,
+      TError,
+      TData,
+      TQueryFnData,
+      TQueryKey
+    >['refetchOnMount'],
+    refetchOnReconnect: refetchOnReconnect as UseInfiniteQueryOptions<
+      TQueryFnData,
+      TError,
+      TData,
+      TQueryFnData,
+      TQueryKey
+    >['refetchOnReconnect'],
+    refetchOnWindowFocus: refetchOnWindowFocus as UseInfiniteQueryOptions<
+      TQueryFnData,
+      TError,
+      TData,
+      TQueryFnData,
+      TQueryKey
+    >['refetchOnWindowFocus'],
  }) as UseSuspenseInfiniteQueryResult<TData, TError>
}
gwansikk commented 1 week ago

@manudeli I think there might be users currently using this component. How about temporarily wrapping it with the code I suggested and proceeding with infiniteQueryOptions in the next version?

like this: https://github.com/toss/suspensive/issues/1015#issuecomment-2199263821

manudeli commented 1 week ago

@manudeli I think there might be users currently using this component. How about temporarily wrapping it with the code I suggested and proceeding with infiniteQueryOptions in the next version?

like this: #1015 (comment)

Cool! Could you make it as Pull Request!? Actually I need this infiniteQueryOptions at now too for my other work