queryx_getx 0.1.1 copy "queryx_getx: ^0.1.1" to clipboard
queryx_getx: ^0.1.1 copied to clipboard

GetX bindings for QueryX — reactive Query, Mutation & InfiniteQuery controllers with .obs state, automatic Obx/GetX rebuilds, and zero manual listener wiring.

QueryX GetX

queryx_getx

Reactive GetX bindings for QueryX.

Query · Mutation · InfiniteQuery

pub.flutter-io.cn likes CI GetX


GetX bindings for queryxQuery, Mutation, and InfiniteQuery exposed as reactive GetxControllers (.obs), so GetX apps get automatic rebuilds via Obx/GetX widgets with zero manual listener wiring.

Like queryx_riverpod, this is a thin adapter, not a second engine: every query still goes through one shared QueryClient — dedup, caching, retry, and invalidation all work exactly like they do in plain queryx.

Setup #

void main() {
  setupQueryxClient(QueryClient(defaultStaleTime: const Duration(minutes: 5)));
  runApp(const MyApp());
}

queryxClient (the getter) throws a clear error if you forget to call setupQueryxClient first — same philosophy as queryx_riverpod's queryxClientProvider: no silent throwaway client that would break cross-widget cache sharing.

Queries #

class UsersScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final users = useQuery<List<User>>(QueryKey(['users']), api.getUsers);
    return Obx(() => users.value.when(
      loading: () => const CircularProgressIndicator(),
      error: (e) => Text(e.message),
      data: (data) => ListView(children: [for (final u in data) Text(u.name)]),
    ));
  }
}

useQuery registers the controller with GetX's dependency injection under key.id — call it again anywhere in the app with an equivalent key and you get back the same controller (one Obx subscription shared, on top of the dedup/caching queryx already does at the QueryClient level).

Call disposeQuery(key) from a StatefulWidget.dispose() if you want the GetX-level controller released eagerly. The cached data itself survives regardless — that's governed by queryx's own cacheTime, independent of the GetX controller's lifecycle.

Dependent / parameterized queries #

Pass a unique tag (or just rely on the key including the parameter, e.g. QueryKey(['user', userId]), which already produces a distinct default tag per user):

final userController = useQuery<User>(
  QueryKey(['user', userId]),
  () => api.getUser(userId),
);

For a query that should only run once another finishes, use enabled:

final orders = useQuery<List<Order>>(
  QueryKey(['orders', userId]),
  () => api.getOrders(userId),
  options: QueryOptions(enabled: userController.value.hasData),
);

Mutations #

final likePost = useMutation<int, void, int>(
  'like-post-1', // tag — mutations don't have an intrinsic key like queries do
  (_) => api.post('/posts/1/like'),
  options: MutationOptions(
    onMutate: (_) async {
      final snapshot = queryxClient.getQueryData<int>(likesKey)!;
      queryxClient.updateQueryData<int>(likesKey, (n) => (n ?? 0) + 1); // instant UI update
      return snapshot;
    },
    onSuccess: (serverCount, _, __) => queryxClient.setQueryData(likesKey, serverCount),
    onError: (error, _, snapshot) => queryxClient.setQueryData(likesKey, snapshot!), // rollback
  ),
);

ElevatedButton(
  onPressed: () => likePost.mutate(null),
  child: const Icon(Icons.favorite),
)

Because queryxClient is reachable globally through GetX's DI, mutation callbacks don't need anything like queryx_riverpod's optionsBuilder(ref) — just reference queryxClient directly inside onMutate/onSuccess.

Infinite queries #

final feed = useInfiniteQuery<Post, int>(
  QueryKey(['posts']),
  initialPageParam: 0,
  fetchPage: (page) => api.getPosts(page: page ?? 0),
);

Obx(() => ListView(
  children: [
    for (final post in feed.value.items) PostTile(post),
    if (feed.value.hasNextPage)
      TextButton(onPressed: feed.fetchNextPage, child: const Text('Load more')),
  ],
));

A note on testing #

Unlike queryx_riverpod (which depends on the pure-Dart riverpod package and is testable with plain dart test), GetX itself (get) is a single combined package that pulls in Flutter — there's no flutter_riverpod-style split. Get.put() schedules an internal onReady() post-frame callback that needs Flutter's binding initialized, so this package's tests run under flutter test, not dart test — see test/query_controller_test.dart.

Installation #

dependencies:
  queryx_getx: ^0.1.0
  get: ^4.6.6
1
likes
160
points
173
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

GetX bindings for QueryX — reactive Query, Mutation & InfiniteQuery controllers with .obs state, automatic Obx/GetX rebuilds, and zero manual listener wiring.

Homepage
Repository (GitHub)
View/report issues

Topics

#getx #networking #caching #state-management

License

MIT (license)

Dependencies

flutter, get, queryx

More

Packages that depend on queryx_getx