GraphQL Flutter

version MIT License All Contributors PRs Welcome

Watch on GitHub Star on GitHub

Table of Contents

Installation

First depend on the library by adding this to your packages pubspec.yaml:

dependencies:
  graphql_flutter: ^0.6.0

Now inside your Dart code you can import it.

import 'package:graphql_flutter/graphql_flutter.dart';

Usage

To use the client it first needs to be initialized with an endpoint and cache. If your endpoint requires authentication you can provide it to the client contructor. If you need to change the api token at a later stage, you can call the setter apiToken on the Client class.

For this example we will use the public GitHub API.

...

import 'package:graphql_flutter/graphql_flutter.dart';

void main() {
  ValueNotifier<Client> client = new ValueNotifier(
    new Client(
      endPoint: 'https://api.github.com/graphql',
      cache: new InMemoryCache(),
      apiToken: '<YOUR_GITHUB_PERSONAL_ACCESS_TOKEN>',
    ),
  );

  ...
}

...

Graphql Provider

In order to use the client, you app needs to be wrapped with the GraphqlProvider widget.

  ...

  return new GraphqlProvider(
    client: client,
    child: new MaterialApp(
      title: 'Flutter Demo',
      ...
    ),
  );

  ...

Queries

Creating a query is as simple as creating a multiline string:

String readRepositories = """
  query ReadRepositories(\$nRepositories) {
    viewer {
      repositories(last: \$nRepositories) {
        nodes {
          id
          name
          viewerHasStarred
        }
      }
    }
  }
"""
    .replaceAll('\n', ' ');

In your widget:

...

new Query(
  readRepositories, // this is the query you just created
  variables: {
    'nRepositories': 50,
  },
  pollInterval: 10, // optional
  builder: ({
    bool loading,
    var data,
    String error,
  }) {
    if (error != '') {
      return new Text(error);
    }

    if (loading) {
      return new Text('Loading');
    }

    // it can be either Map or List
    List repositories = data['viewer']['repositories']['nodes'];

    return new ListView.builder(
      itemCount: repositories.length,
      itemBuilder: (context, index) {
        final repository = repositories[index];

        return new Text(repository['name']);
    });
  },
);

...

Mutations

Again first create a mutation string:

String addStar = """
  mutation AddStar(\$starrableId: ID!) {
    addStar(input: {starrableId: \$starrableId}) {
      starrable {
        viewerHasStarred
      }
    }
  }
"""
    .replaceAll('\n', ' ');

The syntax for mutations is fairly similar to that of a query. The only diffence is that the first argument of the builder function is a mutation function. Just call it to trigger the mutations (Yeah we deliberately stole this from react-apollo.)

...

new Mutation(
  addStar,
  builder: (
    runMutation, { // you can name it whatever you like
    bool loading,
    var data,
    String error,
}) {
  return new FloatingActionButton(
    onPressed: () => runMutation({
      'starrableId': <A_STARTABLE_REPOSITORY_ID>,
    }),
    tooltip: 'Star',
    child: new Icon(Icons.star),
  );
},
  onCompleted: (Map<String, dynamic> data) {
    showDialog(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        title: Text('Thanks for your star!'),
        actions: <Widget>[
          SimpleDialogOption(
            child: Text('Dismiss'),
            onPressed: () {
              Navigator.of(context).pop();
            },
          )
        ],
      );
    }
  );
}),

...

Graphql Consumer

You can always access the client direcly from the GraphqlProvider but to make it even easier you can also use the GraphqlConsumer widget.

  ...

  return new GraphqlConsumer(
    builder: (Client client) {
      // do something with the client

      return new Container(
        child: new Text('Hello world'),
      );
    },
  );

  ...

Offline Cache

The in-memory cache can automatically be saved to and restored from offline storage. Setting it up is as easy as wrapping your app with the CacheProvider widget.

Make sure the CacheProvider widget is inside the GraphqlProvider widget.

...

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new GraphqlProvider(
      client: client,
      child: new CacheProvider(
        child: new MaterialApp(
          title: 'Flutter Demo',
          ...
        ),
      ),
    );
  }
}

...

Roadmap

This is currently our roadmap, please feel free to request additions/changes.

FeatureProgress
Basic queries
Basic mutations
Basic subscriptions🔜
Query variables
Mutation variables
Subscription variables🔜
Query polling
In memory caching
Offline caching
Optimistic results🔜
Client state management🔜

Contributing

Feel free to open a PR with any suggestions! We'll be actively working on the library ourselves.

Contributors

Thanks goes to these wonderful people (emoji key):


Eustatiu Dima

🐛 💻 📖 💡 🤔 👀

Zino Hofmann

🐛 💻 📖 💡 🤔 🚇 👀

Harkirat Saluja

📖 🤔

Chris Muthig

💻 📖 💡 🤔

Cal Pratt

🐛 💻 📖 💡 🤔

This project follows the all-contributors specification. Contributions of any kind are welcome!

Libraries

graphql_flutter