next-unified-query
Version:
React hooks and components for next-unified-query-core
211 lines (206 loc) • 10.3 kB
text/typescript
import * as next_unified_query_core from 'next-unified-query-core';
import { FetchError, QueryConfig, ZodType, FetchConfig, ExtractParams, QueryObserverResult, ExtractQueryData, ApiErrorResponse, InferIfZodSchema, RequestConfig, HttpMethod, NextTypeFetch, z, MutationConfig, QueryClient, QueryClientOptionsWithInterceptors, QueryState } from 'next-unified-query-core';
import React$1, { ReactNode } from 'react';
/**
* 기본 UseQuery 옵션 (공통 속성)
*/
interface BaseUseQueryOptions<T = any> {
cacheKey: readonly unknown[];
params?: Record<string, any>;
schema?: ZodType;
fetchConfig?: Omit<FetchConfig, "url" | "method" | "params" | "data">;
enabled?: boolean;
staleTime?: number;
select?: (data: T) => any;
selectDeps?: any[];
/**
* placeholderData: fetch 전 임시 데이터 또는 이전 데이터 유지
* 값 또는 함수(prevData, prevQuery) 모두 지원
* ReactNode(JSX)도 허용
*/
placeholderData?: T | React.ReactNode | ((prevData: T | React.ReactNode | undefined, prevQuery?: any) => T | React.ReactNode);
/**
* gcTime: 쿼리 데이터가 사용되지 않을 때(구독자가 0이 될 때) 가비지 컬렉션까지의 시간(ms)
* 이는 생명주기 관리 전략으로, maxQueries(메모리 보호)와는 별개로 동작합니다.
* @default 300000 (5분)
*/
gcTime?: number;
}
/**
* URL 기반 UseQuery 옵션
*/
interface UrlBasedUseQueryOptions<T = any> extends BaseUseQueryOptions<T> {
/**
* API 요청 URL
*/
url: string;
/**
* queryFn이 있으면 안됨 (상호 배제)
*/
queryFn?: never;
}
/**
* Custom Function 기반 UseQuery 옵션
*/
interface FunctionBasedUseQueryOptions<T = any> extends BaseUseQueryOptions<T> {
/**
* 복잡한 요청을 위한 커스텀 쿼리 함수
* Options 방식에서는 QueryFetcher만 전달 (GET/HEAD 메서드만 허용)
* 인자: fetcher (QueryFetcher 인스턴스)
*/
queryFn: (fetcher: next_unified_query_core.QueryFetcher) => Promise<T>;
/**
* url이 있으면 안됨 (상호 배제)
*/
url?: never;
}
/**
* UseQuery 옵션
* URL 방식 또는 Custom Function 방식 중 하나를 선택할 수 있음
*/
type UseQueryOptions<T = any> = UrlBasedUseQueryOptions<T> | FunctionBasedUseQueryOptions<T>;
/**
* Schema에서 타입을 추출하는 도우미 타입
*/
type InferSchemaType<T> = T extends {
schema: infer S;
} ? S extends ZodType ? next_unified_query_core.z.infer<S> : any : any;
type UseQueryFactoryOptions<P, T> = Omit<UseQueryOptions<T>, "cacheKey" | "url" | "queryFn" | "params" | "schema" | "fetchConfig"> & (P extends void ? {
params?: P;
} : keyof P extends never ? {
params?: P;
} : {
params: P;
});
/**
* 캐싱과 상태 관리를 제공하는 데이터 페칭 React 훅입니다.
*
* **환경 호환성:**
* - ❌ 서버사이드: 서버 컴포넌트와 호환되지 않음 (React context 사용)
* - ✅ 클라이언트사이드: React context가 있는 React 컴포넌트에서 사용
* - ⚠️ SSR: "use client" 지시어가 있는 클라이언트 컴포넌트에서만 사용
*
* @example
* ```typescript
* // 클라이언트 컴포넌트에서만 사용
* "use client";
* import { useQuery } from 'next-unified-query/react';
*
* function UserProfile({ userId }: { userId: number }) {
* const { data, isLoading, error } = useQuery(api.getUser, { params: userId });
*
* if (isLoading) return <div>Loading...</div>;
* if (error) return <div>Error: {error.message}</div>;
* return <div>Hello {data.name}</div>;
* }
* ```
*/
declare function useQuery<T, E = FetchError>(query: QueryConfig<any, any>, options: UseQueryFactoryOptions<ExtractParams<typeof query>, T>): QueryObserverResult<T, E>;
declare function useQuery<Q extends QueryConfig<any, any>, E = FetchError>(query: Q, options: UseQueryFactoryOptions<ExtractParams<Q>, ExtractQueryData<Q>>): QueryObserverResult<ExtractQueryData<Q>, E>;
declare function useQuery<O extends UseQueryOptions<any> & {
schema: ZodType;
}, E = FetchError>(options: O): QueryObserverResult<InferSchemaType<O>, E>;
declare function useQuery<T, E = FetchError>(options: UseQueryOptions<T>): QueryObserverResult<T, E>;
/**
* Mutation 상태 인터페이스
*/
interface MutationState<TData = unknown, TError = FetchError<ApiErrorResponse>, TVariables = void> {
data: TData | undefined;
error: TError | null;
isPending: boolean;
isSuccess: boolean;
isError: boolean;
}
/**
* 기본 UseMutation 옵션 (공통 속성)
*/
interface BaseUseMutationOptions<TData = unknown, TError = FetchError<ApiErrorResponse>, TVariables = void, TContext = unknown, RequestSchema extends ZodType = ZodType, ResponseSchema extends ZodType = ZodType> {
onMutate?: (variables: TVariables) => Promise<TContext | void> | TContext | void;
onSuccess?: (data: InferIfZodSchema<ResponseSchema, TData>, variables: TVariables, context: TContext | undefined) => Promise<void> | void;
onError?: (error: TError, variables: TVariables, context: TContext | undefined) => Promise<void> | void;
onSettled?: (data: InferIfZodSchema<ResponseSchema, TData> | undefined, error: TError | null, variables: TVariables, context: TContext | undefined) => Promise<void> | void;
invalidateQueries?: string[][] | ((data: InferIfZodSchema<ResponseSchema, TData>, variables: TVariables, context: TContext | undefined) => string[][]);
fetchConfig?: Omit<RequestConfig, "url" | "method" | "params" | "data" | "schema">;
requestSchema?: RequestSchema;
responseSchema?: ResponseSchema;
}
/**
* URL 기반 UseMutation 옵션
*/
interface UrlBasedUseMutationOptions<TData = unknown, TError = FetchError<ApiErrorResponse>, TVariables = void, TContext = unknown, RequestSchema extends ZodType = ZodType, ResponseSchema extends ZodType = ZodType> extends BaseUseMutationOptions<TData, TError, TVariables, TContext, RequestSchema, ResponseSchema> {
/**
* API 요청 URL
*/
url: string | ((variables: TVariables) => string);
/**
* HTTP 메서드
*/
method: HttpMethod;
/**
* mutationFn이 있으면 안됨 (상호 배제)
*/
mutationFn?: never;
}
/**
* Function 기반 UseMutation 옵션 (통일된 시그니처)
*/
interface UnifiedMutationOptions<TData = unknown, TError = FetchError<ApiErrorResponse>, TVariables = any, TContext = unknown, RequestSchema extends ZodType = ZodType, ResponseSchema extends ZodType = ZodType> extends BaseUseMutationOptions<TData, TError, TVariables, TContext, RequestSchema, ResponseSchema> {
/**
* Unified mutation function - 모든 경우에 (variables, fetcher) 패턴 사용
* void mutation인 경우 variables를 _ 또는 무시하고 사용
*/
mutationFn: (variables: TVariables, fetcher: NextTypeFetch) => Promise<InferIfZodSchema<ResponseSchema, TData>>;
/**
* url/method가 있으면 안됨 (상호 배제)
*/
url?: never;
method?: never;
}
/**
* UseMutation 옵션
* URL 방식 또는 Custom Function 방식 중 하나를 선택할 수 있음
*/
type UseMutationOptions<TData = unknown, TError = FetchError<ApiErrorResponse>, TVariables = any, TContext = unknown, RequestSchema extends ZodType = ZodType, ResponseSchema extends ZodType = ZodType> = UrlBasedUseMutationOptions<TData, TError, TVariables, TContext, RequestSchema, ResponseSchema> | UnifiedMutationOptions<TData, TError, TVariables, TContext, RequestSchema, ResponseSchema>;
/**
* UseMutation 결과 인터페이스 (단순화된 시그니처)
*/
interface UseMutationResult<TData = unknown, TError = FetchError<ApiErrorResponse>, TVariables = any> extends MutationState<TData, TError, TVariables> {
mutate: (variables: TVariables, options?: {
onSuccess?: (data: TData, variables: TVariables, context: any) => void;
onError?: (error: TError, variables: TVariables, context: any) => void;
onSettled?: (data: TData | undefined, error: TError | null, variables: TVariables, context: any) => void;
}) => void;
mutateAsync: (variables?: TVariables, options?: {
onSuccess?: (data: TData, variables: TVariables, context: any) => void;
onError?: (error: TError, variables: TVariables, context: any) => void;
onSettled?: (data: TData | undefined, error: TError | null, variables: TVariables, context: any) => void;
}) => Promise<TData>;
reset: () => void;
}
/**
* useMutation 오버로드 선언
*/
declare function useMutation<TVariables = any, TError = FetchError<ApiErrorResponse>, TContext = unknown, RequestSchema extends ZodType = ZodType, ResponseSchema extends ZodType = ZodType>(options: UseMutationOptions<unknown, TError, TVariables, TContext, RequestSchema, ResponseSchema> & {
responseSchema: ResponseSchema;
}): UseMutationResult<z.infer<ResponseSchema>, TError, TVariables>;
declare function useMutation<TData = unknown, TError = FetchError<ApiErrorResponse>, TVariables = any, TContext = unknown>(factoryConfig: MutationConfig<TVariables, TData, TError, TContext>, overrideOptions?: Partial<BaseUseMutationOptions<TData, TError, TVariables, TContext>>): UseMutationResult<TData, TError, TVariables>;
declare function useMutation<TData = unknown, TError = FetchError<ApiErrorResponse>, TVariables = any, TContext = unknown>(options: UseMutationOptions<TData, TError, TVariables, TContext>): UseMutationResult<TData, TError, TVariables>;
declare function HydrationBoundary({ state, children, }: {
state?: Record<string, QueryState>;
children: ReactNode;
}): React$1.JSX.Element;
interface QueryClientProviderProps {
/**
* QueryClient 인스턴스 (선택사항)
* 제공하지 않으면 자동으로 환경에 맞는 인스턴스를 생성합니다.
*/
client?: QueryClient;
/**
* QueryClient 옵션 (client가 제공되지 않은 경우에만 사용)
*/
options?: QueryClientOptionsWithInterceptors;
children: ReactNode;
}
declare function QueryClientProvider({ client, options, children }: QueryClientProviderProps): React$1.JSX.Element;
declare function useQueryClient(): QueryClient;
export { HydrationBoundary, QueryClientProvider, useMutation, useQuery, useQueryClient };