wheatandcatの開発ブログ

React Nativeで開発しているペペロミア & memoirの技術系記事を投稿してます

Flutterでgraphql_codegenを使って型安全でAPIアクセスを実装する

現状FlutterでAPI接続するにはGraphQLが良さ気だったので実装してみた

リポジトリ

以下で開発

■ Flutter github.com

■ backend github.com

開発構成

モチベーション

Flutterでもgraphql_codegenで型安全で実装はできるので、それを使って開発

実装

graphql_codegenで型安全にするためにbackendから以下のスキーマファイルを取得

src/schema.graphql

type Query {
  categories: [Category]
  category(id: Int!): Category
}
type Category {
  "カテゴリーID"
  id: ID!
  "カテゴリー名"
  name: String!
  "順番"
  order: Int!
}

graphql_codegenでは上記のスキーマファイルとフロントエンド側でアクセスするgqlファイルを元にGraphQLのアクセス用のファイルを自動生成する。

なので、次はフロントエンド側でアクセスに使用するgqlファイルを作成

lib/graphql/category.gql

query Category($id: Int!) {
  category(id: $id) {
    id
    name
    order
  }
}

以下のコマンドでgraphql_codegenに必要ライブラリをインストール

$ flutter pub add --dev graphql_codegen build_runner
$ flutter pub add graphql graphql_flutter flutter_hooks

build_runnerの設定ファイルを作成

build.yaml

targets:
  $default:
    builders:
      graphql_codegen:
        options:
          scopes:
            - lib/graphql/**
          clients:
            - graphql
            - graphql_flutter

以下のコマンドでgraphql_codegenを実行

$ dart run build_runner build

コマンド実行で以下のファイルが生成される

lib/graphql/category.gql.dart

(略)
graphql_flutter.QueryHookResult<Query$Category> useQuery$Category(
        Options$Query$Category options) =>
    graphql_flutter.useQuery(options);
graphql.ObservableQuery<Query$Category> useWatchQuery$Category(
        WatchOptions$Query$Category options) =>
    graphql_flutter.useWatchQuery(options);
(略)

上記で生成したファイルを使用してGraphQLを実行、今回はHooksを使用した方法で実装

lib/app/items/page.dart

import 'package:flutter/material.dart';
import 'package:sampleflutter/components/appBar/common.dart';
import 'package:sampleflutter/graphql/category.gql.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:sampleflutter/utils/graphql.dart';

class Items extends HookWidget {
  final int id;

  const Items({super.key, required this.id});

  @override
  Widget build(BuildContext context) {
    final queryResult = useQuery$Category(
        Options$Query$Category(variables: Variables$Query$Category(id: id)));

    final result = queryResult.result;

    if (result.isLoading) {
      return const Scaffold(
        appBar: CommonAppBar(title: ""),
        body: Center(
          child: CircularProgressIndicator(),
        ),
      );
    }

    final Query$Category$category category = extractGraphQLData(
      data: result.data,
      fieldName: "category",
      fromJson: Query$Category$category.fromJson,
    );

    return Scaffold(
      appBar: const CommonAppBar(title: ""),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.only(left: 10, right: 10),
            child: Card(
              color: Colors.transparent,
              elevation: 0,
              shape: const Border(
                  bottom: BorderSide(color: Colors.white, width: 3)),
              child: ListTile(
                contentPadding: EdgeInsets.zero,
                title: Text(category.name,
                    style: const TextStyle(
(略)

こんな感じで、ほぼReact & GraphQL Code Generatorで開発している時と、ほぼ同じ感覚でFlutterでも開発できるので、なかなか便利でした。
一旦、Flutter & GraphQLで開発を進めて行こうと思います。