KeihakuOh / GraphQL_React_App

0 stars 0 forks source link

graphqlの開発者セットアップについて #2

Open KeihakuOh opened 1 month ago

KeihakuOh commented 1 month ago
const express = require('express');
const expressGraphQL = require('express-graphql').graphqlHTTP;

const app = express();

app.use('/graphql', expressGraphQL({
  graphiql: true
}));

app.listen(4000, () => {
  console.log('Listening');
});

.graphqlHTTPは、このモジュール内に含まれる関数で、GraphQL APIのミドルウェアとして使われます。このミドルウェアは、GraphQLのクエリを処理し、レスポンスを返す役割を持っています。

GraphiQLは、ブラウザ上で動作するGraphQLの「IDE」です。これは「Integrated Development Environment(統合開発環境)」の一種で、GraphQLのリクエストを送信し、レスポンスをリアルタイムで確認できるツールです。

KeihakuOh commented 1 month ago

schema

const graphql = require('graphql');
const axios = require('axios');
const {
  GraphQLObjectType,
  GraphQLString,
  GraphQLInt,
  GraphQLSchema
} = graphql;

const CompanyType = new GraphQLObjectType({
  name: 'Company',
  fields: {
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    description: { type: GraphQLString }
  }
});

const UserType = new GraphQLObjectType({
  name: 'User',
  fields: {
    id: { type: GraphQLString },
    firstName: { type: GraphQLString },
    age: { type: GraphQLInt },
    company: {
      type: CompanyType,
      resolve(parentValue, args) {
        return axios.get(`http://localhost:3000/companies/${parentValue.companyId}`)
          .then(res => res.data);
      }
    }
  }
});

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    user: {
      type: UserType,
      args: { id: { type: GraphQLString } },
      resolve(parentValue, args) {
        return axios.get(`http://localhost:3000/users/${args.id}`)
          .then(resp => resp.data);
      }
    }
  }
});

module.exports = new GraphQLSchema({
  query: RootQuery
});

GraphQLObjectType: GraphQLの型を定義するためのオブジェクト GraphQLString: GraphQLにおける文字列型(String)を定義します GraphQLInt: GraphQLにおける整数型(Int)を定義します。

nameフィールド:このオブジェクト型の名前 argsフィールド: クライアントがuserフィールドをクエリする際に、引数(args)として渡すデータを定義しています。

ーーーーーー 実際の流れ: ステップ1: RootQueryの実行

{
  user(id: "123") {
    id
    firstName
    age
    company {
      id
      name
      description
    }
  }
}

この場合、まずRootQueryのuserフィールドのresolve関数が呼び出され、args.idが渡されてユーザー情報を取得します。

ステップ2: UserTypeのフィールドを解決 ユーザーデータが取得された後、GraphQLはクエリで指定されたフィールド(id、firstName、age、company)を1つずつ見ていきます。

UserTypeのフィールドに基づいてデータを返す: その際、UserTypeで定義されている各フィールド(id、firstName、age)について、クエリに含まれているかどうかを確認します。

もしクエリに含まれていれば、そのフィールドのデータを直接(graphql内部に)返します。 id、firstName、age はユーザーデータの中にすでに存在しているため、GraphQLは追加の処理をせずに、そのまま返します。

フィールドごとにresolve関数がある場合: companyフィールドのようにresolve関数が定義されている場合、そのresolve関数が実行されます(例: parentValue.companyIdを使って会社情報を取得する)。

KeihakuOh commented 1 month ago

parentValue とは何か?

  // 親フィールドが user の場合、ここで parentValue はそのユーザーデータを保持している
  console.log(parentValue); // => { id: "123", firstName: "John Doe", age: 28 }

parentValue は、親のフィールドがリゾルブされた結果が渡される値です。つまり、ネストされたクエリがある場合、親のデータを次のネストされたフィールドのresolve関数で参照できます。 parentValueを使うことで、ネストされたフィールド(例: orders)が、親フィールド(例: user)のデータに基づいて適切なデータを返すことができます。

KeihakuOh commented 1 month ago
const graphql = require('graphql');
const axios = require('axios');
const {
  GraphQLObjectType,
  GraphQLString,
  GraphQLInt,
  GraphQLSchema
} = graphql;

const UserType = new GraphQLObjectType({
  name: 'User',
  fields: {
    id: { type: GraphQLString },
    firstName: { type: GraphQLString },
    age: { type: GraphQLInt }
  }
});

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    user: {
      type: UserType,
      args: { id: { type: GraphQLString } },
      resolve(parentValue, args) {
        return axios.get(http://localhost:3000/users/${args.id})
          .then(resp => resp.data);
      }
    }
  }
});

module.exports = new GraphQLSchema({
  query: RootQuery
});

GraphQLSchemaの中で RootQueryを指定していますが、RootQuery の中ではすでに UserType が参照されています。つまり、RootQuery をエクスポートすることで、自動的にUserTypeも参照される形になっています。

KeihakuOh commented 1 month ago
return axios.get(`http://localhost:3000/users/${args.id}`)
  .then(resp => resp.data);

具体的な流れ axios.get()の呼び出し:

axios.get()は、指定されたURLに対してHTTP GETリクエストを送信します。このリクエストは非同期に行われ、Promiseオブジェクトがすぐに返されます。 Promiseが返された後:

Promiseオブジェクトは、その結果(成功または失敗)が返るまで保留状態になります。リクエストが成功すると、Promiseの状態は「解決済み(fulfilled)」になります。 .then()の実行:

リクエストが成功した後、.then()ブロックが実行され、resp(レスポンスオブジェクト)に対して処理が行われます。この場合、resp.data(レスポンスデータの本体部分)が抽出されて返されます。 resolve関数の戻り値としてPromiseが返る:

resolve関数の戻り値は最終的にPromiseオブジェクトです。GraphQLはこのPromiseが解決されるのを待ち、その結果をクライアントに返します。