Skip to content

Quick Start

Get up and running with Fasq in 5 minutes. This guide focuses on the core QueryBuilder widget, which works with any Flutter setup.

Let’s fetch a list of users and display them.

import 'package:fasq/fasq.dart';
class UsersScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return QueryBuilder<List<User>>(
// 1. Unique key for caching
queryKey: 'users'.toQueryKey(),
// 2. Async function that returns Future<List<User>>
queryFn: () => api.fetchUsers(),
// 3. Builder callback
builder: (context, state) {
if (state.isLoading) {
return const Center(child: CircularProgressIndicator());
}
if (state.hasError) {
return Center(child: Text('Error: ${state.error}'));
}
if (state.hasData) {
return ListView.builder(
itemCount: state.data!.length,
itemBuilder: (context, index) {
final user = state.data![index];
return ListTile(
title: Text(user.name),
subtitle: Text(user.email),
);
},
);
}
return const SizedBox();
},
);
}
}

If you use a specific state management library, you can use the corresponding adapter for a more integrated feel.

// Using fasq_hooks
class UsersScreen extends HookWidget {
@override
Widget build(BuildContext context) {
final state = useQuery('users', () => api.fetchUsers());
if (state.isLoading) return const CircularProgressIndicator();
// ... same UI logic
}
}

Note: Requires fasq_hooks package.

// Using fasq_bloc
BlocProvider(
create: (_) => QueryCubit(key: 'users', queryFn: api.fetchUsers),
child: BlocBuilder<QueryCubit<List<User>>, QueryState<List<User>>>(
builder: (context, state) {
if (state.isLoading) return const CircularProgressIndicator();
// ...
},
),
)

Note: Requires fasq_bloc package.

Add caching behavior by customizing QueryOptions.

QueryBuilder<List<User>>(
queryKey: 'users'.toQueryKey(),
queryFn: () => api.fetchUsers(),
options: QueryOptions(
staleTime: Duration(minutes: 5), // Fresh for 5 minutes (no refetch)
cacheTime: Duration(minutes: 30), // Keep in memory for 30 minutes
),
builder: (context, state) => /* ... */,
)

Use the provided QueryClient to interact with queries manually.

// Refresh (Refetch)
QueryClient().invalidateQuery('users'.toQueryKey());
// Manual Retry (if error)
if (state.hasError) {
ElevatedButton(
onPressed: () => QueryClient().refetchQuery('users'.toQueryKey()),
child: Text('Retry'),
);
}