Apollo와 React Hooks

소개



React Hooks의 등장에 의해 View에 관한 처리와 상태, 로직, 라이프 사이클을 깨끗이 분리할 수 있게 되었습니다. 그런 가운데, 최근 GraphQL 클라이언트인 Apollo도 React Hooks의 대응이 릴리스 되었습니다.

지금까지 Apollo를 이용할 때는 HoC나 render prop을 사용할 필요가 있어, 가독성이 낮다는 문제가 있었습니다.
그래서 이번에는 React Hooks를 이용하여 어떻게 코드를 간결하게 작성할 수 있게 되는지를 소개합니다.

React Hooks 이전 코드



공개된 GraphQL API인 StarWars API를 활용합니다.
  • GraphQL 로디그 중


  • GraphQL 로드 완료



  • 다음 코드에서는 쿼리 구성 요소의 인수에 쿼리를 전달하고 내부 요소에 논리를 작성합니다.
    로드 주위의 처리가 Query 컴퍼넌트의 내용을 상상할 수 없어 이해가 어렵습니다.
    const FETCH_MOVIES = gql`
      {
        allFilms {
          id
          title
        }
      }
    `;
    
    function StarWarsMovies() {
      return (
        <div className="App">
          <h2>Star Wars API Without React Hooks</h2>
          <div>
            <Query query={FETCH_MOVIES}>
              {({ data, error, loading }) => {
                if (loading) return "Loading...";
                if (error) return error;
    
                const films = data.allFilms.map(film => (
                  <div key={film.id}>
                    {film.title}
                    <div />
                  </div>
                ));
                return <div>{films}</div>;
              }}
            </Query>
          </div>
        </div>
      );
    }
    

    React Hooks인 useQuery를 이용한 코드



    실행 결과는 이전과 동일합니다.

    아래 코드에서는 useQuery 인수에 쿼리를 전달하고 loading, error, 응답의 세 가지가 반환됩니다.
    매우 직관적인 함수입니다. 그리고는 이 반환해 온 값을 솔직하게 이용하는 코드를 쓸 뿐입니다.
    render prop에 비해 계층이 줄어들어 매우 간단하게 기술할 수 있게 되었습니다.
    function StarWarsMovies() {
      const { loading, error, data } = useQuery(FETCH_MOVIES);
      if (loading) {
        return "Loading...";
      }
    
      if (error) {
        return error;
      }
    
      const films = data.allFilms.map(film => (
        <div key={film.id}>{film.title}</div>
      ));
    
      return (
        <div className="App">
          <h2>Star Wars API Without React Hooks</h2>
          {films}
        </div>
      );
    }
    

    React Hooks인 useLazyQuery를 이용한 코드



    useLazyQuery는 이 함수를 실행할 때 쿼리 요청을 던지지 않고 함수를 반환합니다.
    이 반환된 함수를 실행하면 쿼리 요청이 발생합니다.
    버튼 클릭시 등 액션 후에 쿼리를 실행하고 싶은 경우에 이용합니다.

    여기가 실행되고 있지 않으면 버튼을 표시하고 버튼을 누르면 GraphQL의 요청이 던집니다.
    그 이외는 방금전과 같습니다.


    function StarWarsMovies() {
      const [loadStarWarsMovies, { called, loading, error, data }] = useLazyQuery(FETCH_MOVIES);
      if (called && loading) {
        return "Loading...";
      }
    
      if (!called) {
        return <button onClick={loadStarWarsMovies}>Load Star Wars Movies</button>;
      }
    
      if (error) {
        return error;
      }
    
      const films = data.allFilms.map(film => (
        <div key={film.id}>{film.title}</div>
      ));
    
      return (
        <div className="App">
          <h2>Star Wars API Without React Hooks</h2>
          {films}
        </div>
      );
    }
    

    요약



    React Hooks의 useQuery에 의해 HoC나 render prop에 비해 매우 간결하게 코드를 쓸 수 있게 되었습니다.
    공식 문서에서도 React Hooks의 useQuery가 표준 설명으로 사용되기 때문에 적극적으로 사용하는 것이 좋습니다.

    또 이번 설명하고 있는 것 외에도 React Hooks에는 그 밖에도 다양한 메리트가 있으므로 꼭 봐 주세요.
  • 빌더 Tokyo 2019 - 선언적 UI
  • React Hooks의 커스텀 훅이 실현하는 세계 - 객체 지향과 OSS
  • 좋은 웹페이지 즐겨찾기