TanStack Query hooks for Flutter | query_kit_hooks

useQuery, useMutation, useInfiniteQuery and the rest of React Query's hooks, on flutter_hooks. They read the same cache, with the same rules, as the four call styles of query_kit_flutter, which this package builds on and re-exports.

Documentation: the hooks guide on query-kit.dualmeta.io · API reference

AI-coded. query_kit is an entirely AI-coded project: all code, tests and documentation were written by AI coding agents (Anthropic's Claude). A human maintainer set the goals and reviews releases, but did not write the code.

A port, not affiliated. The behaviour is TanStack Query's, and upstream's own hook tests are ported case by case and run against these hooks, with thanks to Tanner Linsley and the TanStack team. This package is not affiliated with, endorsed by or connected to them; please take problems to this repository's issues, not to TanStack.

Why a separate package

query_kit_flutter depends on nothing beyond Flutter, so it cannot use flutter_hooks. This package can. If your widgets are already HookWidgets, the hooks read a query the way the rest of your hooks read state. If they are not, you do not need this package: the binding's four call styles do the same job, and none of them is behind the hooks.

Install

flutter pub add query_kit_hooks flutter_hooks

This package brings query_kit_flutter with it and re-exports it, so its import gives you the whole binding. flutter_hooks goes in your pubspec.yaml as well, because your files import it for HookWidget: this package does not re-export it, and the depend_on_referenced_packages lint asks for a direct dependency on every package a file imports.

import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:query_kit_hooks/query_kit_hooks.dart';

Requires Flutter 3.27 or later.

Reading a query

Provide a QueryClient with a QueryClientProvider, exactly as for the binding. Then read a query from a HookWidget:

class TasksScreen extends HookWidget {
  const TasksScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final tasks = useQuery(
      QueryObserverOptions<List<Task>>(
        queryKey: QueryKey(<Object?>['tasks']),
        queryFn: (context) => api.listTasks(signal: context.signal),
      ),
    );

    return switch (tasks) {
      QueryPending() => const Center(child: CircularProgressIndicator()),
      QueryError(:final error) => Center(child: Text('$error')),
      QuerySuccess(:final data) => ListView(
          children: [for (final task in data) Text(task.name)],
        ),
    };
  }
}

The hook takes the same options and returns the same sealed QueryResult as context.query. A different queryKey on a later build switches the same observer to the other query. Unmounting the widget lets the query go.

The hooks in 0.1.0

Hook Does what
useQuery, useSelectQuery one query, with or without select
useInfiniteQuery a paged query
useMutation a mutation, as a MutationController
useQueries, useCombinedQueries a list of queries, raw or combined
useIsFetching, useIsMutating how many queries are fetching, how many mutations are pending
useMutationState, useTypedMutationState a selection over the mutation cache, untyped or typed
usePrefetchQuery, usePrefetchInfiniteQuery start a fetch without reading it
useQueryClient the client of the nearest provider

The hooks that read one result — useQuery, useSelectQuery, useInfiniteQuery, useMutation and useCombinedQueries — take a buildWhen, as the binding's call styles do. useQueries takes none, as QueriesBuilder takes none. No hook rebuilds for a notification carrying what the widget is already showing.

What each hook takes and returns, the rules of hooks, what a throw in build costs and how to test a HookWidget are in the hooks guide.

License and credits

MIT. query_kit is a port of TanStack Query by Tanner Linsley and contributors, whose MIT notice is kept in LICENSE-TANSTACK. The hooks run on flutter_hooks by Remi Rousselet. Bugs and questions go to the issue tracker.

Libraries

query_kit_hooks
TanStack Query's hooks for Flutter: useQuery, useMutation and the rest, on flutter_hooks, reading the same cache as query_kit_flutter's four call styles.