CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-query

Hooks for managing, caching and syncing asynchronous and remote data in React

Pending
Overview
Eval results
Files

queries.mddocs/

Query Operations

Core data fetching functionality with intelligent caching, background updates, and automatic error handling. The useQuery hook is the primary interface for fetching and caching data in React Query.

Capabilities

useQuery Hook

The main hook for fetching data with automatic caching and background updates.

/**
 * Fetch and cache data with automatic background updates
 * @param options - Query configuration options
 * @returns Query result with data, loading states, and utilities
 */
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
  options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>
): UseQueryResult<TData, TError>;

/**
 * Fetch and cache data using separate queryKey and queryFn parameters
 * @param queryKey - Unique identifier for the query
 * @param queryFn - Function that returns data or promise
 * @param options - Additional query configuration
 * @returns Query result with data, loading states, and utilities
 */
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
  queryKey: TQueryKey,
  queryFn: QueryFunction<TQueryFnData, TQueryKey>,
  options?: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>
): UseQueryResult<TData, TError>;

/**
 * Fetch and cache data with optional undefined initial data
 * @param options - Query configuration with optional initialData
 * @returns Query result where data may be undefined
 */
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
  options: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'initialData'> & { 
    initialData?: () => undefined 
  }
): UseQueryResult<TData, TError>;

/**
 * Fetch and cache data with guaranteed initial data
 * @param options - Query configuration with initialData
 * @returns Defined query result where data is never undefined
 */
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
  options: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'initialData'> & { 
    initialData: TQueryFnData | (() => TQueryFnData) 
  }
): DefinedUseQueryResult<TData, TError>;

/**
 * Fetch and cache data with separate parameters and optional undefined initial data
 * @param queryKey - Unique identifier for the query
 * @param options - Query configuration with optional initialData
 * @returns Query result where data may be undefined
 */
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
  queryKey: TQueryKey,
  options?: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryKey' | 'initialData'> & { 
    initialData?: () => undefined 
  }
): UseQueryResult<TData, TError>;

/**
 * Fetch and cache data with separate parameters and guaranteed initial data
 * @param queryKey - Unique identifier for the query
 * @param options - Query configuration with initialData
 * @returns Defined query result where data is never undefined
 */
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
  queryKey: TQueryKey,
  options?: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryKey' | 'initialData'> & { 
    initialData: TQueryFnData | (() => TQueryFnData) 
  }
): DefinedUseQueryResult<TData, TError>;

/**
 * Fetch and cache data with queryKey, queryFn and optional undefined initial data
 * @param queryKey - Unique identifier for the query
 * @param queryFn - Function that returns data or promise
 * @param options - Additional query configuration with optional initialData
 * @returns Query result where data may be undefined
 */
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
  queryKey: TQueryKey,
  queryFn: QueryFunction<TQueryFnData, TQueryKey>,
  options?: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryKey' | 'queryFn' | 'initialData'> & { 
    initialData?: () => undefined 
  }
): UseQueryResult<TData, TError>;

/**
 * Fetch and cache data with queryKey, queryFn and guaranteed initial data
 * @param queryKey - Unique identifier for the query
 * @param queryFn - Function that returns data or promise
 * @param options - Additional query configuration with initialData
 * @returns Defined query result where data is never undefined
 */
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
  queryKey: TQueryKey,
  queryFn: QueryFunction<TQueryFnData, TQueryKey>,
  options?: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryKey' | 'queryFn' | 'initialData'> & { 
    initialData: TQueryFnData | (() => TQueryFnData) 
  }
): DefinedUseQueryResult<TData, TError>;

Usage Examples:

import { useQuery } from "react-query";

// Basic query
const { data, isLoading, error } = useQuery({
  queryKey: ['posts'],
  queryFn: () => fetch('/api/posts').then(res => res.json())
});

// Query with parameters
const { data: user } = useQuery({
  queryKey: ['user', userId],
  queryFn: ({ queryKey }) => fetch(`/api/users/${queryKey[1]}`).then(res => res.json()),
  enabled: !!userId // Only run when userId exists
});

// Query with data transformation
const { data: userNames } = useQuery({
  queryKey: ['users'],
  queryFn: () => fetch('/api/users').then(res => res.json()),
  select: (users) => users.map(user => user.name)
});

// Legacy API style (separate parameters)
const { data } = useQuery(
  ['posts', { page: 1 }],
  ({ queryKey }) => fetchPosts(queryKey[1]),
  {
    staleTime: 5000,
    retry: 3
  }
);

Query Result Interface

The return value from useQuery containing data, loading states, and utilities.

interface UseQueryResult<TData = unknown, TError = unknown> {
  /** The actual data returned by the query function */
  data: TData | undefined;
  /** The error object if the query failed */
  error: TError | null;
  /** True if the query is in an error state */
  isError: boolean;
  /** True if this is the first time the query is loading */
  isLoading: boolean;
  /** True if the query is pending (loading or paused) */
  isPending: boolean;
  /** True if the query succeeded and has data */
  isSuccess: boolean;
  /** True if the query is currently fetching */
  isFetching: boolean;
  /** True if the query is refetching in the background */
  isRefetching: boolean;
  /** Current status of the query */
  status: 'pending' | 'error' | 'success';
  /** Current fetch status */
  fetchStatus: 'fetching' | 'paused' | 'idle';
  /** Function to manually refetch the query */
  refetch: () => Promise<QueryObserverResult<TData, TError>>;
  /** Function to remove the query from cache */
  remove: () => void;
  /** Timestamp when data was last updated */
  dataUpdatedAt: number;
  /** Timestamp when error occurred */
  errorUpdatedAt: number;
  /** Number of times query has failed */
  failureCount: number;
  /** Reason query is paused */
  failureReason: TError | null;
  /** True if query data is stale */
  isStale: boolean;
  /** True if initial data was provided */
  isInitialLoading: boolean;
  /** True if refetch is disabled */
  isRefetchError: boolean;
  /** True if loading first time due to error */
  isLoadingError: boolean;
  /** True if currently paused */
  isPaused: boolean;
  /** True if data exists in cache */
  isPlaceholderData: boolean;
  /** Previous successful data */
  isPreviousData: boolean;
}

interface DefinedUseQueryResult<TData = unknown, TError = unknown> 
  extends Omit<UseQueryResult<TData, TError>, 'data'> {
  /** Data is guaranteed to be defined */
  data: TData;
}

Query Options Interface

Configuration options for useQuery hook.

interface UseQueryOptions<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> {
  /** Unique identifier for the query */
  queryKey?: TQueryKey;
  /** Function that returns data or promise */
  queryFn?: QueryFunction<TQueryFnData, TQueryKey>;
  /** Whether the query should run automatically */
  enabled?: boolean;
  /** Retry configuration */
  retry?: boolean | number | ((failureCount: number, error: TError) => boolean);
  /** Delay between retries */
  retryDelay?: number | ((retryAttempt: number, error: TError) => number);
  /** Time before data is considered stale */
  staleTime?: number;
  /** Time before inactive queries are garbage collected */
  cacheTime?: number;
  /** Interval for automatic refetching */
  refetchInterval?: number | false | ((data: TData | undefined, query: Query) => number | false);
  /** Whether to refetch when window is not focused */
  refetchIntervalInBackground?: boolean;
  /** When to refetch on component mount */
  refetchOnMount?: boolean | "always";
  /** When to refetch on window focus */
  refetchOnWindowFocus?: boolean | "always";
  /** When to refetch on network reconnection */
  refetchOnReconnect?: boolean | "always";
  /** Transform or select data subset */
  select?: (data: TQueryFnData) => TData;
  /** Initial data to use before first fetch */
  initialData?: TData | (() => TData);
  /** Placeholder data while loading */
  placeholderData?: TData | (() => TData);
  /** Callback on successful query */
  onSuccess?: (data: TData) => void;
  /** Callback on query error */
  onError?: (error: TError) => void;
  /** Callback after query settles (success or error) */
  onSettled?: (data: TData | undefined, error: TError | null) => void;
  /** React context for QueryClient */
  context?: React.Context<QueryClient | undefined>;
  /** Whether to throw errors to error boundaries */
  useErrorBoundary?: boolean | ((error: TError, query: Query) => boolean);
  /** Whether to suspend component rendering */
  suspense?: boolean;
  /** Whether to keep previous data during refetch */
  keepPreviousData?: boolean;
  /** Network mode configuration */
  networkMode?: 'online' | 'always' | 'offlineFirst';
  /** Notification mode configuration */
  notifyOnChangeProps?: Array<keyof UseQueryResult> | 'all';
  /** Additional metadata */
  meta?: QueryMeta;
}

Query Function Interface

The function that actually fetches data for the query.

type QueryFunction<T = unknown, TQueryKey extends QueryKey = QueryKey> = (
  context: QueryFunctionContext<TQueryKey>
) => T | Promise<T>;

interface QueryFunctionContext<TQueryKey extends QueryKey = QueryKey, TPageParam = any> {
  /** The query key */
  queryKey: TQueryKey;
  /** AbortSignal for request cancellation */
  signal?: AbortSignal;
  /** Page parameter for infinite queries */
  pageParam?: TPageParam;
  /** Additional metadata */
  meta: QueryMeta | undefined;
}

type QueryKey = readonly unknown[];

type QueryMeta = Record<string, unknown>;

Advanced Usage Patterns

Dependent Queries

Queries that depend on data from other queries:

function Profile({ userId }: { userId: string }) {
  // First, get the user
  const { data: user } = useQuery({
    queryKey: ['user', userId],
    queryFn: () => fetchUser(userId)
  });

  // Then get user's posts (depends on user data)
  const { data: posts } = useQuery({
    queryKey: ['posts', user?.id],
    queryFn: () => fetchUserPosts(user.id),
    enabled: !!user?.id
  });

  return <div>{/* render user and posts */}</div>;
}

Dynamic Query Keys

Query keys that change based on component state:

function SearchResults() {
  const [searchTerm, setSearchTerm] = useState('');
  const [filters, setFilters] = useState({});

  const { data: results } = useQuery({
    queryKey: ['search', searchTerm, filters],
    queryFn: ({ queryKey }) => searchAPI(queryKey[1], queryKey[2]),
    enabled: searchTerm.length > 2
  });

  return (
    <div>
      <input 
        value={searchTerm}
        onChange={(e) => setSearchTerm(e.target.value)}
      />
      {/* render results */}
    </div>
  );
}

Error Handling

const { data, error, isError, refetch } = useQuery({
  queryKey: ['posts'],
  queryFn: fetchPosts,
  retry: (failureCount, error) => {
    // Retry up to 3 times for server errors
    if (error.status >= 500 && failureCount < 3) {
      return true;
    }
    return false;
  },
  onError: (error) => {
    console.error('Query failed:', error);
    // Could show toast notification, log to analytics, etc.
  }
});

if (isError) {
  return (
    <div>
      <p>Something went wrong: {error.message}</p>
      <button onClick={() => refetch()}>Try Again</button>
    </div>
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-react-query

docs

context.md

error-handling.md

index.md

infinite-queries.md

mutations.md

parallel-queries.md

queries.md

ssr.md

status.md

tile.json