Simplified Graphql Implementations for Query and Mutation in Flutter

What is Graphql

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

One of the basic problems with conventional REST is the failure of the client to demand a personalized data set. In addition to that, running and controlling multiple endpoints is another difficulty as clients are mostly needed to request data from diversified endpoints.

There are three types of operations that GraphQL models:

  • query — a read‐only fetch(HTTP GET request).
  • mutation — a write followed by a fetch.
  • subscription — a long‐lived request that fetches data in response to source events.

Let’s do it!

We will be using “https://countries.trevorblades.com/ “ API

I will walk you through how to get your query parameters

We want to query the country, the documentation expects code: ID! as a param, you can decide on the response you want from the Country object.

Tips in working with Graphql

  • Curly brackets {} — — SelectionSet e.g{id firstName lastName}
  • Brackets () — — (passing argument ) e.g ($input: String!)
  • Exclamation mark! — — Required parameter

Here is the API response base on what we structured.

Let jump into a flutter

Copy those codes to your pubspec.yaml

graphql_flutter: ^4.0.1

Let create a class to reuse when we want to make a request

GraphQLConfig.dart

I created an avenue to pass a token to the class, you can remove it if you don't need to pass that.

import "package:flutter/material.dart";
import "package:graphql_flutter/graphql_flutter.dart";

class GraphQLConfig {


static String token = "your can get it from a secured storage";
static HttpLink httpLink = HttpLink(
'https://countries.trevorblades.com/',
);

///if you want to pass token
static ValueNotifier<GraphQLClient> graphInit() {
// We're using HiveStore for persistence,
// so we need to initialize Hive.


final AuthLink authLink = AuthLink(
getToken: () async => 'Bearer $token',
);

final Link link = authLink.concat(httpLink);

ValueNotifier<GraphQLClient> client = ValueNotifier(
GraphQLClient(
link: link,
// The default store is the InMemoryStore, which does NOT persist to disk
cache: GraphQLCache(
store: HiveStore(),
),
),
);

return client;
}






GraphQLClient clientToQuery() {
AuthLink authLink = AuthLink(
getToken: () async => 'Bearer $token',
);

final Link link = authLink.concat(httpLink);
return GraphQLClient(
cache: GraphQLCache(
store: HiveStore(),
),
link: link,
);
}
}

In your main.dart

import 'package:flutter/material.dart';
import 'package:flutter_graphql_implementation/server/GraphQLConfig.dart';
import 'package:flutter_graphql_implementation/uiScreens/home_screen.dart';

import 'package:graphql_flutter/graphql_flutter.dart';

Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// We're using HiveStore for persistence,
// so we need to initialize Hive.
await initHiveForFlutter();

// launch app
runApp(MyApp());
}

class MyApp extends StatelessWidget {

MyApp();

@override
Widget build(BuildContext context) {
//GraphQLConfig init
ValueNotifier<GraphQLClient> client = GraphQLConfig.graphInit();
return GraphQLProvider(
client: client,
child: MaterialApp(
title: 'Flutter Graphql Demo',


home: HomeScreen(),

),
);
}
}

Let create a data class called Country.dart

class Country {
String capital;
String code;
String currency;
String emoji;
String emojiU;
String name;
String phone;

Country({this.capital, this.code, this.currency, this.emoji, this.emojiU, this.name, this.phone});

factory Country.fromJson(Map<String, dynamic> json) {
return Country(
capital: json['capital'],
code: json['code'],
currency: json['currency'],
emoji: json['emoji'],
emojiU: json['emojiU'],
name: json['name'],
phone: json['phone'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['capital'] = this.capital;
data['code'] = this.code;
data['currency'] = this.currency;
data['emoji'] = this.emoji;
data['emojiU'] = this.emojiU;
data['name'] = this.name;
data['phone'] = this.phone;
return data;
}
}

Then just call your GraphQLConfig class to make a request.

I have added implementations for both queries and mutations,

import 'package:flutter_graphql_implementation/model/Country.dart';
import 'package:flutter_graphql_implementation/server/GraphQLConfig.dart';
import 'package:graphql_flutter/graphql_flutter.dart';


class ApiClients{



String countryQuery = '''
query getCountry(\$input: ID!) {
country(code: \$input) {
code
name
phone
capital
currency
emoji
emojiU
}
}
''';

///Example on how to implement query to get country
Future<Country> getCountry(String code) async {

Country country = Country();
try {

///initializing GraphQLConfig
GraphQLConfig graphQLConfiguration = GraphQLConfig();
GraphQLClient _client = graphQLConfiguration.clientToQuery();
QueryResult result = await _client.query(

QueryOptions(
document: gql(countryQuery),
variables: {
"input": "$code"
}
),
);


if(result.hasException){
print(result.exception?.graphqlErrors[0]?.message);

}else if(result.data!= null){
country = Country.fromJson(result.data["country"]);

return country;
}


}catch(e){
print(e);
return country;

}




}





///THIS IS A SAMPLE FOR MAKING Mutation REQUEST
/// Replace the login with your query request
///login
static String login(String email,
String password) {
return '''
mutation{
login(data: {
input:"$email",
password: "$password"
}){
token
user{
_id
email
phonenumber
referralCode
username
emailVerified
}
}
}
''';
}



///Example on how to implement mutations
Future<String> Login(String email, password) async {
try {
///initializing GraphQLConfig
GraphQLConfig graphQLConfiguration = GraphQLConfig();
GraphQLClient _client = graphQLConfiguration.clientToQuery();
QueryResult result = await _client.mutate(
MutationOptions(
document: gql(login(email,password)), // this
),
);
if(result.hasException){
print(result.exception?.graphqlErrors[0]?.message);

}else if(result.data!= null){
// parse your response here and return
// var data = User.fromJson(result.data["register"]);
}

return "";
}catch(e){
print(e);
return "";

}
}

}

Here is the API bind on mobile.

I tried my best to make this lesson clear and short as much as possible. Please, bear with me for any error you might encounter. I am just trying to share my knowledge.

If you have any questions or corrections, I will be glad to know.

Project Repo — https://github.com/muryno/flutter_graphql_implementation

You can mail me personally — murainoy@yahoo.com

Github | Linkedin | Twitter

Thanks for reading.

Senior mobile developer & Backend engineer ~ Flutter|Dart | JAVA | Kotlin| Spring framework | Golang