Setup

reactJS에서 graphQL API를 사용하기위해서는 graphQL server가 동작하고 서버와 통신하도록 구성해야한다. ApolloClient를 인스턴스하면 전달 받은 uri에 있는 graphQL 데이터를 가져올 수 있다.

import { ApolloClient, InMemoryCache } from "@apollo/client";

const client = new ApolloClient({
  uri: "<http://localhost:4000/>",
  cache: new InMemoryCache(),
});

export default client;

ApolloProvider

Apollo server을 실행시킨 상태에서 graphQL 데이터를 react로 가져오는 방법은react component를 ApolloProvider component로 감싸면 된다. rudex의 Provider처럼 말이다. client.js에서 작성한 ApolloClient 인스턴스를 가져와 ApolloProvider props에 전달하면 react component에서 @apollo/client hooks를 통해 graphQL 데이터를 가져오게 된다.

import { ApolloProvider } from "@apollo/client";
import client from "./client";

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

useApolloClient hook을 이용하여 Movies component가 마운트되면 graphQL데이터를 qurey하여 그중에 원하는 데이터를 Promise.then에서 뽑아 사용한다. 그리고 graphQL server에서 데이터 변화가 생기면 useEffect가 동작하여 실시간으로 업데이트를 진행한다.

import { useApolloClient, gql } from "@apollo/client";
import { useEffect, useState } from "react";

function Movies() {
  const [movies, setMovies] = useState([]);
  const client = useApolloClient();
  useEffect(() => {
    client
      .query({
        query: gql`
          {
            allMovies {
							id
              title
            }
          }
        `,
      })
      .then((results) => setMovies(results.data.allMovies));
  }, [client]);
  return (
    <ul>
      {movies.map((movie) => (
        <li key={movie.id}>{movie.title}</li>
      ))}
    </ul>
  );
}

export default Movies;

useQuery

useQuery를 호출하면 client, data, previousData, error, loading, networkStatus, called 정보를 반환 받는다. 이처럼 개발자 개발자 경험이 좋은 hooks을 선언형 코드(declarative code)라고 부른다. 반면, useApolloClient를 호출하고 useState호출하고 useEffect를 호출하는 등 기능에 모든 단계를 구현하는 것을 명령형 코드(imperative code)라고 한다. 그리고 declarative code를 실현해 줄 useQuery를 사용하여 useApolloClient코드를 리펙토링 하는 코드를 구현한다.

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

const GET_MOVIES = gql`
  query getMovies {
    allMovies {
      title
      id
    }
  }
`;

function Movies() {
  const { data, loading, error } = useQuery(GET_MOVIES);
  if (loading) {
    return <h1>Loading...</h1>;
  }
  if (error) {
    return <h1>Could not fetch :(</h1>;
  }
  return (
    <ul>
      <h1>Movies</h1>
      {data.allMovies.map((movie) => (
        <li key={movie.id}>{movie.title}</li>
      ))}
    </ul>
  );
}

export default Movies;

useQuery을 호출하는 것만으로 gql을 정의할 뿐 useState, useEffect, useApolloClient기능을 useQuery하나만으로 모두 구현하였다. 이러한 개념적인 코드 방식을 선언형 코드(declarative code)라 부른다.


useQuery Variables

movies.js에 Link를 추가하여 movie page로 전환되는 코드를 구현할 것이다. 우선 movies.js return을 다음과 같이 구현한다. movies.js를 보면 Link의 to props에 URL를 입력하였는데 App.js의 movie component가 들어간 Route path props와 같은 형태의 URL인걸 확인할 수 있다. 즉, Link component는 Route와 연결하는 역할을 한다.