KeihakuOh / GraphQL_React_App

0 stars 0 forks source link

GraphQLについて #7

Open KeihakuOh opened 2 days ago

KeihakuOh commented 2 days ago

Query Fragments(クエリフラグメント) は、GraphQLのクエリ内で再利用可能な部分

fragment UserFields on User {
  id
  firstName
  age
}

query {
  user(id: "123") {
    ...UserFields
  }
}
KeihakuOh commented 2 days ago
const mutation = new GraphQLObjectType({
  name: 'Mutation',
  fields: {
    addUser: {
      type: UserType,
      args: {
        firstName: { type: new GraphQLNonNull(GraphQLString) },
        age: { type: GraphQLInt },
        companyId: { type: GraphQLString }
      },
      resolve(parentValue, { firstName, age, companyId }) {
        return axios.post('http://localhost:3000/users', { firstName, age, companyId })
          .then(res => res.data);
      }
    }
  }
});

GraphQLNonNullはnullだと許せないって意味

type: UserType, // ここでミューテーションの戻り値がUserTypeであることを指定

KeihakuOh commented 2 days ago

nameを定義する必要性:

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

このクエリで使われている user フィールドの型は UserType です。UserTypeの name: 'User' がスキーマ内で指定されていることで、GraphQLはこのクエリが User 型に基づいたデータを要求していると理解します。

KeihakuOh commented 1 day ago

GraphQLクライアントとしてのライブラリ(Lokka vs Apollo vs Relay)

Lokka

Lokkaは、シンプルで軽量なGraphQLクライアントです。比較的古いライブラリであり、状態管理やキャッシングの機能は提供していませんが、シンプルさが魅力

const { Lokka } = require('lokka');
const { Transport } = require('lokka-transport-http');

// GraphQLエンドポイントを指定してクライアントを作成
const client = new Lokka({
  transport: new Transport('https://your-graphql-endpoint.com/graphql')
});

// クエリを送信し、データを取得
client.query(`
  {
    user(id: "1") {
      name
      email
    }
  }
`).then(result => {
  console.log(result);
}).catch(error => {
  console.error(error);
});

Apollo

特徴 状態管理(Apollo Clientを使ったローカル状態の管理) 高度なキャッシング リアルタイムのサブスクリプションサポート リアクティブなUIと親和性が高い(Reactなどとの統合がスムーズ)

import { ApolloClient, InMemoryCache, gql, ApolloProvider, useQuery } from '@apollo/client';

// Apollo Clientの設定
const client = new ApolloClient({
  uri: 'https://your-graphql-endpoint.com/graphql',
  cache: new InMemoryCache(),
});

// クエリを定義
const GET_USER = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      name
      email
    }
  }
`;

// コンポーネントでクエリを実行
function User({ userId }) {
  const { loading, error, data } = useQuery(GET_USER, {
    variables: { id: userId },
  });

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <div>
      <h1>{data.user.name}</h1>
      <p>{data.user.email}</p>
    </div>
  );
}

// アプリケーション全体にApolloProviderを適用
function App() {
  return (
    <ApolloProvider client={client}>
      <User userId="1" />
    </ApolloProvider>
  );
}

export default App;

Relay

Relayは、Facebookが開発した高度に最適化されたGraphQLクライアントで、大規模なアプリケーションやパフォーマンスが重要な場面でよく使われます。Apolloに比べてやや複雑ですが、効率的なデータ取得、キャッシング、パフォーマンスの最適化が特徴です。

KeihakuOh commented 1 day ago

GraphQLサーバとしてのライブラリ(Apollo vs GraphQL express)

どっちがいいとかはないが、apolloの方は将来変動ありそう

Apollo

// Apollo Serverのインポート
const { ApolloServer, gql } = require('apollo-server');

// サンプルユーザーデータ
const users = [
  { id: '1', name: '太郎', email: 'taro@example.com' },
  { id: '2', name: '花子', email: 'hanako@example.com' },
];

// GraphQLスキーマの定義
const typeDefs = gql`
  type User {
    id: ID!
    name: String!
    email: String!
  }

  type Query {
    user(id: ID!): User
    users: [User]
  }
`;

// リゾルバの定義
const resolvers = {
  Query: {
    // 特定のIDに基づいてユーザー情報を取得
    user: (parent, args) => users.find(user => user.id === args.id),
    // すべてのユーザー情報を取得
    users: () => users,
  },
};

// Apollo Serverを作成
const server = new ApolloServer({ typeDefs, resolvers });

// サーバーの起動
server.listen().then(({ url }) => {
  console.log(`🚀 サーバーが起動しました: ${url}`);
});

GraphQL express

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

const CompanyType = new GraphQLObjectType({
  name: 'Company',
  fields: () => ({
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    description: { type: GraphQLString },
    users: {
      type: new GraphQLList(UserType),
      resolve(parentValue, args) {
        return axios
          .get(`http://localhost:3000/companies/${parentValue.id}/users`)
          .then((res) => res.data);
      },
    },
  }),
});

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);
      },
    },
    company: {
      type: CompanyType,
      args: { id: { type: GraphQLString } },
      resolve(parentValue, args) {
        return axios
          .get(`http://localhost:3000/companies/${args.id}`)
          .then((resp) => resp.data);
      },
    },
  },
});

const mutation = new GraphQLObjectType({
  name: 'Mutation',
  fields: {
    addUser: {
      type: UserType,
      args: {
        firstName: { type: new GraphQLNonNull(GraphQLString) },
        age: { type: GraphQLInt },
        companyId: { type: GraphQLString },
      },
      resolve(parentValue, { firstName, age, companyId }) {
        return axios
          .post('http://localhost:3000/users', { firstName, age, companyId })
          .then((res) => res.data);
      },
    },
    deleteUser: {
      type: UserType,
      args: {
        id: { type: new GraphQLNonNull(GraphQLString) },
      },
      resolve(parentValue, { id }) {
        return axios
          .delete(`http://localhost:3000/users/${id}`)
          .then((res) => res.data);
      },
    },
    editUser: {
      type: UserType,
      args: {
        id: { type: new GraphQLNonNull(GraphQLString) },
        firstName: { type: GraphQLString },
        age: { type: GraphQLInt },
        companyId: { type: GraphQLString },
      },
      resolve(parentValue, args) {
        return axios
          .patch(`http://localhost:3000/users/${args.id}`, args)
          .then((res) => res.data);
      },
    },
  },
});

module.exports = new GraphQLSchema({
  mutation,
  query: RootQuery,
});
KeihakuOh commented 1 day ago

GraphQL Expressについて

Expressサーバーは、複数のルート(例えば、/, /api, /graphql など)を設定できます。GraphQL Expressは、このルートの1つとしてGraphQLの機能を提供します。GraphQL Express自体はサーバではなく、Expressサーバの中で動作するルートミドルウェアです。したがって、GraphQL Expressだけではサーバとは言えません。GraphQL Expressを使うには、必ずExpressサーバが動作している必要があり、GraphQLはそのサーバの一部として機能します。

ーーーーーー より広義のサーバの定義: ソフトウェアサーバ: 例えば、ExpressやNode.jsなどのサーバアプリケーションは、ポート番号を監視し、HTTPリクエストを受け付けてレスポンスを返します。ポート番号をリッスンして、ネットワーク経由でアクセスできるサービスを提供する場合が多い。 物理サーバ: データセンターなどに設置され、複数のサーバアプリケーションを動作させるための実際のコンピュータ。 仮想サーバ: 物理サーバ上で仮想的に動作し、複数のサーバを1つの物理サーバで運用できるもの。

KeihakuOh commented 9 hours ago
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

// Apollo Client を作成
const client = new ApolloClient({
  uri: 'https://example.com/graphql', // 自分のGraphQLサーバーのURL
  cache: new InMemoryCache()           // キャッシュの設定
});

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root')
);

Apollo Provider は、React コンポーネントに GraphQL サーバーと通信するための Apollo Client を使えるようにするためのもの。

KeihakuOh commented 1 hour ago
import React, { Component } from 'react';
import gql from 'graphql-tag';
import { graphql } from 'react-apollo';

class SongList extends Component {
  renderSongs() {
    if (this.props.data.loading) {
      return <div>Loading...</div>;
    }

    return this.props.data.songs.map(song => {
      return <li key={song.title}>{song.title}</li>;
    });
  }

  render() {
    return (
      <div>
        <ul>
          {this.renderSongs()}
        </ul>
      </div>
    );
  }
}

const query = gql`
  {
    songs {
      title
    }
  }
`;

export default graphql(query)(SongList);

graphql(query) は Apollo Client が提供する HOC 関数を返します。 その返された HOC 関数に SongList を渡すことで、Apollo Client は SongList コンポーネントに自動的に GraphQL のデータフェッチ機能を追加します。 結果として、SongList コンポーネントは props を通してデータを受け取り、そのデータを表示できます。

↑これができるのはApolloProviderのおかげ