GraphQL & Apollo


GraphQL


REST APIの限界

  • overfetching
    APIから受信したデータは,特定の情報のみが必要であるが,すべて受信しなければならない.
  • underfetching
    1つのAPIに必要な情報がない場合は、2つのリクエストを同時に受信する必要があります.
  • ☝🏻 GraphQLは、最小限のリクエストで必要な情報のみを受信することができ、データの浪費とAPI回数を減らすことができます.

    GraphQLによるデータ交換


    リクエスト(query)

  • REST API GET要求と同じすべてのデータ
  • query {
      teams {
        id
        manager
        office
        extension_number
        mascot
        cleaning_duty
        project
      }
    }
  • チームに必要なデータのみを要求する(REST APIのキャプチャを解決する)
  • query {
      teams {
        manager
        office
      }
    }
    
    query {
      team(id: 1) {
        manager
        office
      }
    }
  • チーム情報およびチームメンバーの情報は、2回の要求ではなく、1回の要求(REST APIでの欠落解決)
  • query {
      team(id: 1) {
        manager
        office
        members {
          first_name
          last_name
        }
      }
    }
    
    query {
      teams {
        manager
        office
        mascot
      }
      roles {
        id
        requirement
      }
    }

    追加、変更、削除(変異)

    mutation {
      // 추가 : postTeam
      // 수정 : editTeam
      // 삭제 : deleteTeam
      postTeam (input: {
        manager: "John Smith"
        office: "104B"
        extension_number: "#9982"
        mascot: "Dragon"
        cleaning_duty: "Monday"
        project: "Lordaeron"
      }) {
        manager
        office
        extension_number
        mascot
        cleaning_duty
        project
      }
    }

    GraphQLのメリット

  • 必要な情報のみ提供
    オーバーホールの問題を解消し、データ転送量
  • を減少する.
  • は、複数の層の情報を同時に受信することができる
    未キャプチャの問題を解決し、要求を減らす
  • ednpointですべてのリクエストを処理
    1つのURIからすべてのリクエストを要求できます.
  • Apollo

  • GraphQLは単なる説明、フォーマットであり、GraphQL(データの要求と返信)
  • を実装するためのソリューションが必要である.
  • Apolloはソリューションの1つです
    その他のソリューションの表示>
  • 特長

  • のバックエンドおよびフロントエンドは、
  • を提供する.
  • 簡単で使いやすい設定
  • 豊富な機能を提供
  • Apolloサーバ:バックエンドサーバ
  • Apolloクライアント:フロントエンドWeb
  • Apolloクライアントの使用

  • モジュール
  • をインストール
    npm install @apollo/client graphql
  • モジュールimport
  • // ...
    import { ApolloProvider } from '@apollo/client';
    import { ApolloClient, InMemoryCache } from '@apollo/client'
    // ...
    // app.js
    // ...
    const client = new ApolloClient({
      uri: 'http://localhost:4000',
      cache: new InMemoryCache()
    });
    // ...
      return (
        <div className="App">
          <ApolloProvider client={client}>
            <header className="App-header">
              <h1>Company Management</h1>
              <nav>
                <ul>
                  {NavMenus()}
                </ul>
              </nav>
            </header>
            <main>
              {mainComp[menu]}
            </main>
          </ApolloProvider>
        </div>
      );
    //   ...

    ApolloClient


    REST APIのaxiosのような役割は,対応するuriと通信できる.
  • クライアント:GraphQLサーバのAPOLLOクライアントオブジェクト
  • uri:GraphQLサーバアドレス
  • cache:メモリキャッシュによりキャッシュ
  • を管理し、受信したデータを再受信する必要がない

    ApolloProvider


    内部要素を囲むことで、内部要素はApolloクライアントを介してサーバと通信することができます.

    サーバからのデータの取得


    リクエスト・オブジェクトの作成
    // ...
    const GET_ROLES = gql`
      query GetRoles {
        roles {
          id
        }
      }
    `;
    // ...
    リクエスト・オブジェクトを使用したデータの受信
    // ...
      function AsideItems () {
        const { loading, error, data } = useQuery(GET_ROLES);
        if (loading) return <p className="loading">Loading...</p>
        if (error) return <p className="error">Error :(</p>
        //...
      }
    // ...
  • ロード:サーバから情報を受信すると
  • が表示される.
  • error:要求エラー時に
  • を返す
  • データ:必要に応じて情報を取得
  • データの削除

    // ...
    // delete 요청 변수
    const DELETE_TEAM = gql`
      mutation DeleteTeam($id: ID!) {
        deleteTeam(id: $id) {
          id
        }
      }
    `
    // ...
      function execDeleteTeam () {
        if (window.confirm('이 항목을 삭제하시겠습니까?')) {
          // 함수 실행
          deleteTeam({variables: {id: contentId}})
        }
      }
    
      const [deleteTeam] = useMutation(
       //요청 변수가 실행되고 이의 결과로 onCompleted가 실행
      DELETE_TEAM, { onCompleted: deleteTeamCompleted })
      
      //onCompleted의 실행 함수
      function deleteTeamCompleted (data) {
        console.log(data.deleteTeam)
        alert(`${data.deleteTeam.id} 항목이 삭제되었습니다.`)
        setContentId(0)
      }
     // ...
    ☝🏻 データが削除された場合、リストをリフレッシュする必要がありますか?
    const { loading, error, data, refetch } = useQuery(GET_TEMAS)
  • useQueryのrefetchを使用して、データの再ロード操作を行います.
  • // ...
    let refetchTeams
    // ...
    const { loading, error, data, refetch } = useQuery(GET_TEMAS)
    refetchTeams = refetch
    // ...
    function deleteTeamCompleted (data) {
      // ...
      alert(`${data.deleteTeam.id} 항목이 삭제되었습니다.`)
      refetchTeams()
    }
    // ...
    変更と追加も同じ構造で行います.

    Fragment

  • 複数のクエリに使用可能な再利用可能フィールドセット
  • の重複データを低減することにより、コード
  • 全体を簡略化する.
    繰り返し使用する要素をパーティションに分離
    const Names = gql`
      fragment names on People {
        first_name
        last_name
      }
    `
    const HealthInfo = gql`
      fragment healthInfo on People {
        sex
        blood_type
      }
    `
    const WorkInfo = gql`
      fragment workInfo on People {
        serve_years
        role
        team
        from
      }
    `
    クエリーに適用
    const GET_PEOPLE = gql`
      query GetPeople {
      people {
        id
        ...names
        ...healthInfo
        }
      }
      ${Names}
      ${HealthInfo}
    `;
    ヤルコのYouTube講座を見て書いたものです
    ヤルコ講座へ向かいます>