LoginSignup
2
0

More than 1 year has passed since last update.

ApolloClient × Custom HookでGrahQLサーバのデータを取得する

Posted at

はじめに

GrahQLをサポートするApolloClientと、React CustomHookを使って、サーバ上のデータを取得する方法を紹介します。

サンプルイメージ

image.png

今回はバックエンドGrahQLサーバとして、SpaceXが提供しているGrahQL APIを利用します。

前提

create-react-app等で、既にReactプロジェクトが作成されていること。

手順

  1. ライブラリインストール
  2. AppolloClientの設定
  3. useQueryでデータ取得

ライブラリインストール

下記を実行し、ApolloClientをインストールする。

npm install @apollo/client graphql

AppolloClientの設定

上位のコンポーネント(index.jsとか)で必要なオブジェクトをimportする。

index.js
import {
  ApolloClient,
  InMemoryCache,
  ApolloProvider
} from "@apollo/client";

ApolloClientをSpaceXのGraphQLサーバと接続するように設定し、インスタンス化する。
(ここで指定するcacheは、ApolloClientを通じてやり取りしたデータのキャッシュを保持するオブジェクトのこと。cache内のデータはApolloProviderにラップされているコンポーネントならどこからでも参照できます。)

index.js
const client = new ApolloClient({
  uri: 'https://api.spacex.land/graphql/',
  cache: new InMemoryCache()
});

その後、下記のようにGraphQLサーバと接続するコンポーネントをApolloProviderでラップしてあげる。(ApolloProvider配下にいる場合のみ、引数として受け渡されたclientを使ってリクエストを投げることができます。)

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

ここまでのindex.js全体

index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {
  ApolloClient,
  InMemoryCache,
  ApolloProvider,
} from "@apollo/client";

const client = new ApolloClient({
  uri: 'https://api.spacex.land/graphql/',
  cache: new InMemoryCache()
})

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

useQueryでデータ取得

ここから、データ取得のロジックを作成していきます。

下記を実行し、GrahQLサーバへのリクエストクエリ発行に必要なオブジェクトをimportします。

App.js
import {
  useQuery,
  gql
} from "@apollo/client";

クエリ作成

gqlを利用して、クエリを作成します。
下記クエリはSpaceX GrahQL APIから、指定した名前の船情報(船名・画像・id)を取得するクエリです。

App.js
  const GET_SHIPS = gql`
  query GetShips() {
    ships(find: {name: 'American Champion'}) {
      name
      image
      id
    }
  }
  `;

クエリのリクエスト

作成したクエリをuseQueryを使って、リクエストします。

useQuery{ loading, error, data }を返却します。
ロード中であればloading
エラーが発生すればerror
正常にデータが取得出来たらdataを返却します。

上記以外にもuseQueryはいろいろ便利なもの返却するので、下記参照してみてください。
https://www.apollographql.com/docs/react/data/queries/#usequery-api

App.js
  const shipName = '';

  const { loading, error, data } = useQuery(GET_SHIPS ,{
    variables: {name: shipName},
  });

  if (loading) return 'loading';
  if (error) return 'error';

  return {
    shipData:data.ships
  }

上記ロジックをカスタムフックにまとめたコードが下記になります。

App.js
import './App.css';
import {
  useQuery,
  gql
} from "@apollo/client";
import React from 'react';

function useExchangeRates() {
  const GET_SHIPS = gql`
  query GetShips() {
    ships(find: {name: "American Champion"}) {
      name
      image
      id
    }
  }
  `;

  const shipName = 'American Champion';

  const { loading, error, data } = useQuery(GET_SHIPS);

  if (loading) return 'loading';
  if (error) return 'error';

  return {
    shipData:data.ships
  }
}

function ShowshipData(props){
    if(!props.shipData){
      return(<p>no data</p>);
    }else if (props.shipData === 'loading'){
      return(<p>loading</p>);
    }else if(props.shipData === 'error'){
      return(<p>loading</p>);
    }

    return props.shipData.map(({ name, image }) => (
      <div>
        <p>{name}</p>
        <img src={image} alt=''/>
      </div>
    ));
}

function App() {
  console.log("App rerendered");
  const {shipData} = useExchangeRates();

  return (
    <div className="App">
      <div>
        <ShowshipData shipData={shipData}/>
      </div>
    </div>
  );
}

export default App;

以上が、GrahQLサーバのデータを取得する方法になります。

おまけ

リクエストの引数(variables)を変えて、再度データ取得を行う

上記コード例の場合、クエリのvariablesが固定値(American Champion)です。

任意のvariablesを指定かつ、一度実行したクエリを手軽に再実行する方法を紹介します。

クエリ作成

クエリを下記の通り修正します。
GetShipsクエリが、引数としてnameを受け取る宣言をしてます。

App.js
function useExchangeRates() {
  const GET_SHIPS = gql`
  query GetShips($name: String!) {
    ships(find: {name: $name}) {
      name
      image
      id
    }
  }
  `;

クエリのリクエスト

useQueryの第二引数で指定しているvariablesがクエリの引数になります。(今回で言うと船名)

App.js
  const shipName = 'other ship';

  const { loading, error, data, refetch } = useQuery(GET_SHIPS ,{
    variables: {name: shipName},
  });

上記実行すると、指定した船名のデータを取得することができます。

補足:
上記のようにuseQueryの返り値として、refetchを取得しておけば、次回データ取得の際に下記のように利用することができます。

App.js
refetch({
    variables: {name: shipName}
  })

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0