Skip to main content

qora_flutter 1.3.1 copy "qora_flutter: ^1.3.1" to clipboard
qora_flutter: ^1.3.1 copied to clipboard

A Flutter implementation for Qora, bringing powerful async state management, automatic caching, and offline-first capabilities to the widget tree.

qora_flutter #

pub.dev CI likes pub points

Flutter integration for Qora, the server-state layer for apps that have to keep working offline. Bind server data to your UI with one widget: cached data on the first frame, background refresh, refetch on resume and on reconnect.

Part of the Qora monorepo.

Features #

Feature Description
Declarative UI QoraBuilder renders cached data on the first frame and keeps it during refetches and errors
Lifecycle aware Stale queries refetch when the app returns to the foreground
Network aware Queries pause while offline and refetch when the connection is restored
Offline writes QoraMutationBuilder queues mutations made offline and replays them on reconnect
Zero boilerplate Loading, error, and data states handled in one place

Install #

dependencies:
  qora_flutter: ^1.3.0

qora_flutter automatically includes qora and connectivity_plus as dependencies; no extra packages needed.

Setup #

Wrap your app with QoraScope.auto once. It creates and owns the lifecycle and connectivity managers:

import 'package:flutter/foundation.dart';
import 'package:qora_flutter/qora_flutter.dart';

void main() {
  final client = QoraClient(
    config: const QoraClientConfig(debugMode: kDebugMode),
  );

  runApp(QoraScope.auto(client: client, child: const MyApp()));
}

Pass your own FlutterLifecycleManager / FlutterConnectivityManager to the default QoraScope constructor when you need custom settings.

Fetch and display data #

QoraBuilder<T> fetches on mount, caches the result, and rebuilds on every state change:

QoraBuilder<User>(
  queryKey: ['users', userId],
  fetcher: () => api.getUser(userId),
  builder: (context, state, fetchStatus) => switch (state) {
    Loading(:final previousData) => previousData != null
        ? UserCard(user: previousData, isRefreshing: true)
        : const CircularProgressIndicator(),
    Success(:final data) => UserCard(user: data),
    Failure(:final error, :final previousData) => ErrorScreen(
        message: error.toString(),
        onRetry: () => context.qora.invalidate(['users', userId]),
      ),
    _ => const SizedBox.shrink(),
  },
)

Invalidate after a mutation #

await api.createPost(payload);
context.qora.invalidate(['posts']);
context.qora.invalidateWhere((k) => k.firstOrNull == 'posts');

Every QoraBuilder subscribed to a matching key re-fetches automatically.

Write while offline #

With offlineQueue: true, a mutation triggered offline returns an optimistic result immediately and is replayed in order when the device reconnects:

QoraMutationBuilder<Comment, String, void>(
  mutator: (text) => api.postComment(text),
  options: MutationOptions(
    offlineQueue: true,
    optimisticResponse: (text) => Comment.draft(text),
    invalidates: [['comments']],
  ),
  builder: (context, state, mutate) => switch (state) {
    MutationSuccess(:final data, :final isOptimistic) => ListTile(
        title: Text(data.text),
        trailing: isOptimistic ? const Icon(Icons.schedule) : null,
      ),
    MutationFailure(:final error) => ErrorBanner(error),
    _ => TextButton(
        onPressed: state.isPending ? null : () => mutate('Nice post'),
        child: const Text('Send'),
      ),
  },
)

The queue is held in memory: it survives connectivity changes, not an app restart.

Optimistic updates #

final client = context.qora;
final key = ['users', userId];

final snapshot = client.getQueryData<User>(key);

client.setQueryData<User>(key, user.copyWith(name: newName));

try {
  final updated = await api.updateUser(userId, newName);
  client.setQueryData<User>(key, updated);
} catch (_) {
  client.restoreQueryData<User>(key, snapshot);
}

Observe without fetching #

QoraStateBuilder<T> mirrors a query's state without triggering a fetch; ideal for badges, counters, or secondary displays:

QoraStateBuilder<List<Notification>>(
  queryKey: ['notifications'],
  builder: (context, state) {
    final count = state.dataOrNull?.length ?? 0;
    return Badge(label: Text('$count'), child: const Icon(Icons.notifications));
  },
)

Documentation #

Full guides and API reference: qora.meragix.dev

2
likes
160
points
214
downloads

Documentation

Documentation
API reference

Publisher

verified publishermeragix.dev

Weekly Downloads

A Flutter implementation for Qora, bringing powerful async state management, automatic caching, and offline-first capabilities to the widget tree.

Homepage
Repository (GitHub)
View/report issues
Contributing

License

MIT (license)

Dependencies

connectivity_plus, flutter, qora

More

Packages that depend on qora_flutter