GraphQL in Flutter

GraphQL is a query language for APIs. GraphQL provides an understandable and complete description of the data in your API and provides the client the power to ask and get the data exactly they need, and nothing more.

GraphQL is like a buffet dinner, where the users can take any item as per their need and exclude others.

Applications using GraphQL are very fast and stable as they control the data they get, not the server.

Using GraphQL we can get many resources in a single request. GraphQL queries access not just the property of one resource but also smoothly follow references between the properties. Applications that are using GraphQL can be faster even on slow mobile network connections.

With GraphQL, we can add new fields and types without affecting existing queries. By using a single evolving version, GraphQL provides applications continuous access to fresh and new features and encourages cleaner and more maintainable server code.

For example, we have the following table in our database.

Continents {
name
code
countries{
name
}
}

We have a model for continents . The fields represent the properties of Continents.

  • name is the name of the continent
  • code is the code of the continent
  • countries the list of countries on the continents
  • name is the name of the countries

Using REST API, we can fetch continents as

{ "data": {
"continents":[
{
"name":"Africa",
"code":"AF",
"countries":[
{
"name":"Angola"
}
]
},
{
"name":"Asia",
"code":"AS",
"countries":[
{
"name":"Nepal"
}
]
}
]
}
}

As we can see, with REST all the properties of each continent and country are returned, even if we do not need them. We might only need continents and code but we are getting country also.

GraphQL helps in removing this redundancy. With GraphQL, we can get the properties we want to be returned, as:

query {
continents {
name
code
}
}

Here we are telling the server that we only need the name and code from Continent table.

It serves us exactly what we need.



{
"data": {
"continents": [
{
"name": "Africa",
"code": "AF"
},
{
"name": "Antarctica",
"code": "AN"
},
{
"name": "Asia",
"code": "AS"
},
{
"name": "Europe",
"code": "EU"
},
{
"name": "North America",
"code": "NA"
},
{
"name": "Oceania",
"code": "OC"
},
{
"name": "South America",
"code": "SA"
}
]
}
}

 

 

Before going inside the coding first, let’s discuss the topics we are going to use when using GraphQL in Flutter.

  • HttpLink -> It is used to set up the endpoint or the URL of the backend server.
  • GraphQLClient -> It is used to fetch the query/mutation from the endpoint of GraphQL and to connect to the GraphQL server too.
  • GraphQLCache -> It is used to cache our mutation and queries. It consists of an argument options where we pass the type of store in its operation of caching.
  • GraphQLProvider -> This is the widget that wraps the Widget so as to make queries/mutations.
  • GraphQLClient -> It is passed to the GraphQLProvider . GraphQLProvider makes this client available to all widgets in the tree.
  • Query -> It is the widget used to make queries to the GraphQL server.
  • Mutation -> This widget is used to make mutations to the GraphQL server.
  • ValueNotifier ->It is a change notifier that holds a single value. When an old value is changed with a new value it notifies the listeners

 

 

First, we need to add the dependencies, graphql_flutter in pubsec.yaml file.

dependencies:
graphql_flutter: ^5.1.0

For using this widget, we need to import it.

import 'package:graphql_flutter/graphql_flutter.dart';

Then we define HttpLink and client for the GraphQLProvider.

final HttpLink httpLink = HttpLink("https://countries.trevorblades.com/");final ValueNotifier<GraphQLClient> client = ValueNotifier<GraphQLClient>(
GraphQLClient(
link: httpLink,
cache: GraphQLCache(store: HiveStore()),
),
);

The URL of the GraphQL is created using HttpLink , which defines the URL of the GraphQL endpoint.

The cache is passed to the GraphQLClient to tell the cache mechanism to use.

The instance of the GraphQLClient is passed to a ValueNotifier .This ValueNotifier is used to hold the single value and consists of the listeners when a single value changes. graphql_flutter uses it to notify its tree widgets when the data from a GraphQL endpoint gets changed, making graphql_flutter more reactive.

Then, before making GraphQL queries and mutations, we must have to wrap our root widget with GraphQLProvider . It must be provided GraphQLClient instance to its client property.

GraphQLProvider(
client: client,
child: MaterialApp(
title: 'GraphQL Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage()),
)

Queries

For making a query, we use the Query widget.

 
 
Query(
          options: QueryOptions(
              document: gql(query),
              variables: const <String, dynamic>{"code": "AF"}),
          builder: (result, {fetchMore, refetch}) {
            if (result.isLoading) {
              return const Center(
                child: CircularProgressIndicator(),
              );
            }
            if (result.data == null) {
              return const Center(
                child: Text("Data Not Found!!!"),
              );
            }
            return ListView.builder(
                itemCount: result.data!['continent']['countries'].length,
                itemBuilder: (context, index) {
                  return ListTile(
                    title: Text(
                      result.data!['continent']['countries'][index]["name"],
                    ),
                    subtitle: Text(
                        result.data!['continent']['countries'][index]["code"]),
                  );
                });
          }),
 
 

Here ListView widget is wrapped by Query widget where we render the list of the countries associated with Africa with code AS from the GraphQL server. Hence we must wrap the widget with Query where we want to display the data fetched by it.

The Query widget must not be the top-most widget in a tree. It can be placed anywhere else provided the widget that will make use of its data is underneath or wrapped by it.

Also, the Query widget has two properties passed to it: options and builder.

options

final String query = r"""
query GetContinent($code : ID!){
continent(code:$code){
name
countries{
name
code
}
}
}
""";
options: QueryOptions(
document: gql(query),
variables: const <String, dynamic>{"code": "AF"}),

The configuration of the query is passed to Query the widget. The options , parameter is an instance of the QueryOptions which exposes the properties we use to set options for the Query widget.

The document property is used to set or pass the query we want the Query widget to perform. Here we pass the query string:

final String query = r"""
query GetContinent($code : ID!){
continent(code:$code){
name
countries{
name
code
}
}
}
""";

builder

It is the function property. It is called when the Query widget makes the request to the server. It is called with the data from the query and is used to fetch more for pagination and re-fetch the data.

 

Conclusion

We have covered a lot in this article. Here we learned how to use GraphQL with Flutter.

If you learned something new or want to suggest something then please let me know in the comment.

If you loved the article click on 👏 icon which provides motivation on delivering you all the new things.

Also, follow to get updated on exciting articles and projects.

Learning by sharing gives a great impact on the learning process and makes the community bigger and bigger.

Sharing is a magnet that attracts other enthusiasts toward you.

Hence, let’s take a small step toward making our learning community bigger.

Share this article with your friends or tweet about the article if you loved it.

Buy Me a Coffee

0
Would love your thoughts, please comment.x
()
x