Skip to main content
useQuery is an auto-generated hook that automatically triggers data fetching, subscribes your component to cached data, and re-renders as the loading status changes.

Overview

The hook is generated from your API definition using createApi. For an endpoint named getPosts, the generated hook will be useGetPostsQuery.
export const postsApi = createApi({
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: (build) => ({
    getPosts: build.query<Post[], void>({
      query: () => '/posts',
    }),
  }),
});

export const { useGetPostsQuery } = postsApi;

Signature

const result = useXxxQuery(arg, options?);
arg
QueryArg | Signal<QueryArg> | (() => QueryArg | SkipToken)
required
The argument to pass to the query function. Can be:
  • A static value
  • A signal
  • A function returning a value or skipToken
options
UseQueryOptions
Optional configuration object or signal:

Return Value

Returns a signal object with query state and methods:
data
Signal<ResultType | undefined>
The returned data from the query. Access with result.data() for fine-grained reactivity
isLoading
Signal<boolean>
true if the query is loading for the first time (no data yet)
isFetching
Signal<boolean>
true if the query is currently fetching
isSuccess
Signal<boolean>
true if the query has succeeded
isError
Signal<boolean>
true if the query has errored
error
Signal<Error | undefined>
The error object if the query failed
refetch
() => void
Function to manually refetch the data

Usage Examples

Basic Usage

import { useGetPostsQuery } from './api';

@Component({
  selector: 'app-posts',
  template: `
    @if (postsQuery.isLoading()) {
      <p>Loading...</p>
    }
    @if (postsQuery.isError()) {
      <p>Error: {{ postsQuery.error() }}</p>
    }
    @if (postsQuery.data(); as posts) {
      @for (post of posts; track post.id) {
        <div>{{ post.title }}</div>
      }
    }
  `,
})
export class PostsComponent {
  postsQuery = useGetPostsQuery();
}

With Signal Parameters

export class PostDetailsComponent {
  postId = input.required<number>();
  postQuery = useGetPostQuery(this.postId);
}

With Function Parameters

export class PostDetailsComponent {
  postId = signal(1);
  
  postQuery = useGetPostQuery(() => this.postId());
}

With skipToken

import { skipToken } from 'ngrx-rtk-query';

export class PostDetailsComponent {
  postId = input<number | undefined>();
  
  // Only fetch when postId is defined
  postQuery = useGetPostQuery(
    () => this.postId() ?? skipToken
  );
}

With Options

export class PostDetailsComponent {
  postId = input.required<number>();
  
  postQuery = useGetPostQuery(this.postId, {
    pollingInterval: 5000, // Refetch every 5 seconds
    refetchOnFocus: true,
  });
}

With selectFromResult

export class PostTitleComponent {
  postId = input.required<number>();
  
  // Only subscribe to title changes
  postQuery = useGetPostQuery(this.postId, {
    selectFromResult: ({ data, isLoading }) => ({
      title: data?.title,
      isLoading,
    }),
  });
}

Fine-Grained vs Coarse-Grained Reactivity

// Fine-grained: Only re-renders when isLoading changes
{{ postsQuery.isLoading() }}

// Coarse-grained: Re-renders when any property changes
{{ postsQuery().isLoading }}
Use fine-grained reactivity (query.property()) for better performance. Only use coarse-grained (query().property) when you need multiple properties at once.

See Also

Build docs developers (and LLMs) love