Integrating GraphQL APIs Using graphql flutter
May 9, 2025



Summary
Summary
Summary
Summary
The article details how to set up graphql_flutter in a Flutter app, configure the GraphQL client, execute queries and mutations, and manage state and cache for scalable, real-time-capable data interactions.
The article details how to set up graphql_flutter in a Flutter app, configure the GraphQL client, execute queries and mutations, and manage state and cache for scalable, real-time-capable data interactions.
The article details how to set up graphql_flutter in a Flutter app, configure the GraphQL client, execute queries and mutations, and manage state and cache for scalable, real-time-capable data interactions.
The article details how to set up graphql_flutter in a Flutter app, configure the GraphQL client, execute queries and mutations, and manage state and cache for scalable, real-time-capable data interactions.
Key insights:
Key insights:
Key insights:
Key insights:
Client Setup: Combine
HttpLink
,AuthLink
, andHiveStore
to configure a secure, persistent GraphQL client.Query Execution: Use
Query
andMutation
widgets or the imperative API for flexible data handling.State Management: GraphQL’s normalized cache keeps UI in sync with minimal boilerplate.
Pagination & Fetching: Use
fetchMore
andrefetch
to handle dynamic data loads and pagination.Cache Policies: Fine-tune performance with
CachePolicy
options likenetworkOnly
andcacheFirst
.Real-Time Ready: Extend your setup with subscriptions for live updates.
Introduction
Integrating GraphQL APIs in Flutter unlocks a flexible, efficient data-fetching paradigm. Unlike REST, GraphQL lets clients request exactly the data they need in a single round-trip. The graphql_flutter package provides robust tools to connect your Flutter app to any GraphQL endpoint, with built-in caching, error handling, and subscription support. This tutorial walks you through an intermediate integration, covering setup, client configuration, query/mutation execution, and state management.
Setting up graphql_flutter
Begin by adding dependencies to your pubspec.yaml:
dependencies:
flutter:
sdk: flutter
graphql_flutter: ^5.1.0
flutter_dotenv: ^5.0.2 # for managing env variables
Run flutter pub get. If you use environment variables for endpoints or auth tokens, configure flutter_dotenv in your main.dart:
await dotenv.load(fileName: ".env");
// dotenv.env['GRAPHQL_ENDPOINT']
Ensure your GraphQL server supports CORS (for web) or proper SSL certificates (for mobile).
Configuring the GraphQL Client
The core of any GraphQL integration is the GraphQLClient. It manages network links, cache, and authentication. Wrap your app with GraphQLProvider:
final httpLink = HttpLink(dotenv.env['GRAPHQL_ENDPOINT']);
final authLink = AuthLink(
getToken: () async => 'Bearer ${dotenv.env['AUTH_TOKEN']}',
);
final link = authLink.concat(httpLink);
final graphQLClient = GraphQLClient(
cache: GraphQLCache(store: HiveStore()),
link: link,
);
void main() async {
await initHiveForFlutter();
runApp(
GraphQLProvider(
client: ValueNotifier(graphQLClient),
child: MyApp(),
),
);
}
Key points:
• HttpLink: Defines the endpoint URL.
• AuthLink: Attaches JWT or API token.
• HiveStore: Persists cache between app launches.
• initHiveForFlutter(): Initializes Hive for Flutter.
Executing Queries and Mutations
With the client in place, use Query and Mutation widgets or the lower-level API for imperative calls.
Using the Query Widget
class UserList extends StatelessWidget {
final String fetchUsers = """
query GetUsers {
users {
id
name
email
}
}
""";
@override
Widget build(BuildContext context) {
return Query(
options: QueryOptions(document: gql(fetchUsers)),
builder: (result, {fetchMore, refetch}) {
if (result.hasException) {
return Text('Error: ${result.exception.toString()}');
}
if (result.isLoading) {
return CircularProgressIndicator();
}
final users = result.data!['users'] as List<dynamic>;
return ListView.builder(
itemCount: users.length,
itemBuilder: (_, i) {
final user = users[i];
return ListTile(
title: Text(user['name']),
subtitle: Text(user['email']),
);
},
);
},
);
}
}
Imperative Mutations
void addUser(GraphQLClient client, String name, String email) async {
final mutation = """
mutation CreateUser(\$name: String!, \$email: String!) {
createUser(input: {name: \$name, email: \$email}) {
id
}
}
""";
final result = await client.mutate(MutationOptions(
document: gql(mutation),
variables: {'name': name, 'email': email},
));
if (result.hasException) {
print('Mutation error: ${result.exception}');
} else {
print('User created with ID: ${result.data!['createUser']['id']}');
}
}
Managing State and Caching
GraphQL shines with its normalized cache, automatically updating queries when mutations occur. You can:
• Refetch queries using refetch() in widget builders.
• Use fetchMore for pagination.
• Write directly to the cache via client.writeQuery and client.writeFragment.
• Define cache policies (CachePolicy.networkOnly, CachePolicy.cacheFirst, etc.) in QueryOptions.
Example of pagination with fetchMore:
options: QueryOptions(
document: gql(paginatedQuery),
variables: {'offset': 0, 'limit': 10},
),
builder: (result, { fetchMore, refetch }) {
// On scroll to bottom:
fetchMore!(FetchMoreOptions(
variables: {'offset': currentCount},
updateQuery: (previous, fetchMoreResult) {
final oldList = previous['items'] as List;
final newList = fetchMoreResult!['items'] as List;
return {'items': [...oldList, ...newList]};
},
));
// ...
}
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
By following this tutorial, you’ve integrated a GraphQL API in Flutter using graphql_flutter. You’ve set up your client, executed queries and mutations, and managed caching for optimal UX. Beyond basic operations, explore subscriptions to handle real-time data and advanced cache updates for complex UIs.
With GraphQL mastery and tools like Vibe Studio, you’re well-equipped to build scalable, performant Flutter applications.
Introduction
Integrating GraphQL APIs in Flutter unlocks a flexible, efficient data-fetching paradigm. Unlike REST, GraphQL lets clients request exactly the data they need in a single round-trip. The graphql_flutter package provides robust tools to connect your Flutter app to any GraphQL endpoint, with built-in caching, error handling, and subscription support. This tutorial walks you through an intermediate integration, covering setup, client configuration, query/mutation execution, and state management.
Setting up graphql_flutter
Begin by adding dependencies to your pubspec.yaml:
dependencies:
flutter:
sdk: flutter
graphql_flutter: ^5.1.0
flutter_dotenv: ^5.0.2 # for managing env variables
Run flutter pub get. If you use environment variables for endpoints or auth tokens, configure flutter_dotenv in your main.dart:
await dotenv.load(fileName: ".env");
// dotenv.env['GRAPHQL_ENDPOINT']
Ensure your GraphQL server supports CORS (for web) or proper SSL certificates (for mobile).
Configuring the GraphQL Client
The core of any GraphQL integration is the GraphQLClient. It manages network links, cache, and authentication. Wrap your app with GraphQLProvider:
final httpLink = HttpLink(dotenv.env['GRAPHQL_ENDPOINT']);
final authLink = AuthLink(
getToken: () async => 'Bearer ${dotenv.env['AUTH_TOKEN']}',
);
final link = authLink.concat(httpLink);
final graphQLClient = GraphQLClient(
cache: GraphQLCache(store: HiveStore()),
link: link,
);
void main() async {
await initHiveForFlutter();
runApp(
GraphQLProvider(
client: ValueNotifier(graphQLClient),
child: MyApp(),
),
);
}
Key points:
• HttpLink: Defines the endpoint URL.
• AuthLink: Attaches JWT or API token.
• HiveStore: Persists cache between app launches.
• initHiveForFlutter(): Initializes Hive for Flutter.
Executing Queries and Mutations
With the client in place, use Query and Mutation widgets or the lower-level API for imperative calls.
Using the Query Widget
class UserList extends StatelessWidget {
final String fetchUsers = """
query GetUsers {
users {
id
name
email
}
}
""";
@override
Widget build(BuildContext context) {
return Query(
options: QueryOptions(document: gql(fetchUsers)),
builder: (result, {fetchMore, refetch}) {
if (result.hasException) {
return Text('Error: ${result.exception.toString()}');
}
if (result.isLoading) {
return CircularProgressIndicator();
}
final users = result.data!['users'] as List<dynamic>;
return ListView.builder(
itemCount: users.length,
itemBuilder: (_, i) {
final user = users[i];
return ListTile(
title: Text(user['name']),
subtitle: Text(user['email']),
);
},
);
},
);
}
}
Imperative Mutations
void addUser(GraphQLClient client, String name, String email) async {
final mutation = """
mutation CreateUser(\$name: String!, \$email: String!) {
createUser(input: {name: \$name, email: \$email}) {
id
}
}
""";
final result = await client.mutate(MutationOptions(
document: gql(mutation),
variables: {'name': name, 'email': email},
));
if (result.hasException) {
print('Mutation error: ${result.exception}');
} else {
print('User created with ID: ${result.data!['createUser']['id']}');
}
}
Managing State and Caching
GraphQL shines with its normalized cache, automatically updating queries when mutations occur. You can:
• Refetch queries using refetch() in widget builders.
• Use fetchMore for pagination.
• Write directly to the cache via client.writeQuery and client.writeFragment.
• Define cache policies (CachePolicy.networkOnly, CachePolicy.cacheFirst, etc.) in QueryOptions.
Example of pagination with fetchMore:
options: QueryOptions(
document: gql(paginatedQuery),
variables: {'offset': 0, 'limit': 10},
),
builder: (result, { fetchMore, refetch }) {
// On scroll to bottom:
fetchMore!(FetchMoreOptions(
variables: {'offset': currentCount},
updateQuery: (previous, fetchMoreResult) {
final oldList = previous['items'] as List;
final newList = fetchMoreResult!['items'] as List;
return {'items': [...oldList, ...newList]};
},
));
// ...
}
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
By following this tutorial, you’ve integrated a GraphQL API in Flutter using graphql_flutter. You’ve set up your client, executed queries and mutations, and managed caching for optimal UX. Beyond basic operations, explore subscriptions to handle real-time data and advanced cache updates for complex UIs.
With GraphQL mastery and tools like Vibe Studio, you’re well-equipped to build scalable, performant Flutter applications.
Query Smarter, Visually
Query Smarter, Visually
Query Smarter, Visually
Query Smarter, Visually
Vibe Studio and Steve let you integrate GraphQL APIs into your Flutter app with visual tools, live data previews, and no boilerplate.
Vibe Studio and Steve let you integrate GraphQL APIs into your Flutter app with visual tools, live data previews, and no boilerplate.
Vibe Studio and Steve let you integrate GraphQL APIs into your Flutter app with visual tools, live data previews, and no boilerplate.
Vibe Studio and Steve let you integrate GraphQL APIs into your Flutter app with visual tools, live data previews, and no boilerplate.
References
References
References
References
Join a growing community of builders today
Join a growing
community
of builders today
Join a growing
community
of builders today










© Steve • All Rights Reserved 2025


© Steve • All Rights Reserved 2025


© Steve • All Rights Reserved 2025


© Steve • All Rights Reserved 2025