Skip to main content

Installation

query_kit comes as two packages, and you add the one that matches what you are building:

PackageForDepends on
query_kitPure Dart: a CLI, a server, a shared data packageclock, meta
query_kit_flutterA Flutter appFlutter, meta, query_kit

In a Flutter app​

flutter pub add query_kit_flutter

Or by hand, in pubspec.yaml:

dependencies:
flutter:
sdk: flutter
query_kit_flutter: ^1.0.0

The binding re-exports the core, so one import gives you the whole surface — the client, the options, the results and the widgets:

import 'package:query_kit_flutter/query_kit_flutter.dart';

If a file of yours imports package:query_kit/query_kit.dart directly — a data layer you keep free of Flutter, say — list query_kit in your pubspec.yaml as well. Dart's depend_on_referenced_packages lint asks for it, and it is right to: a package you import is a package you depend on.

In pure Dart​

dart pub add query_kit
import 'package:query_kit/query_kit.dart';

Everything the cache does — staleness, retries, cancellation, mutations, infinite queries — is in the core. What the binding adds is the Flutter side: the provider that maps the app lifecycle onto focus, and the four ways to read a query in a widget. Without it, you call client.mount() yourself; see using the core without Flutter.

A common split in a larger app: a data package that depends on query_kit only and holds the keys and the options functions, and the app, which depends on query_kit_flutter and reads them. The data package then runs its tests with dart test, no Flutter needed.

No third-party dependency​

Neither package pulls in anything beyond the Dart team's clock and meta — not flutter_hooks, not a signals package, not connectivity_plus, not an HTTP client. You bring the HTTP client (query functions shows dio and package:http) and, if you want reconnect refetches, the connectivity source (connectivity shows how to plug any package in). You should not have to adopt somebody's state management to use a cache.

Requirements​

FloorNotes
query_kitDart SDK ^3.6.0No Flutter. Runs on the VM and compiled to JavaScript; both are tested.
query_kit_flutterFlutter >=3.27.0 (which ships Dart 3.6)Tested on 3.27 as well as current stable.

Platforms: the core runs everywhere Dart does. The binding is exercised on the web by the examples' end-to-end suites; the other platforms are untested rather than unsupported — it uses nothing platform-specific beyond AppLifecycleState.

Most of the type safety is there without configuration. Three analyzer settings make the rest of it visible, and the packages themselves are built with them:

# analysis_options.yaml
include: package:flutter_lints/flutter.yaml

analyzer:
language:
strict-casts: true
strict-inference: true
strict-raw-types: true

linter:
rules:
- unawaited_futures
  • strict-inference reports the one options literal inference cannot type: a key-only one with neither a queryFn nor a type argument, which Dart would otherwise make dynamic. See type safety in Dart.
  • strict-raw-types reports a QueryResult or QueryObserverOptions written without its type argument.
  • unawaited_futures reports a client.invalidateQueries(...) or client.query(...) whose future nobody awaits. Await it, or mark a deliberate fire-and-forget with unawaited(...) from dart:async.

Next​

The quick start — a provider, a first query, and a write that refreshes it.

In React Query

The split mirrors @tanstack/query-core and @tanstack/react-query, except that the Flutter package re-exports the core, so an app needs one import. See differences from TanStack Query.