Graphql-hooks 를 활용한 re-rendering 기능 구현

React 는 버전 16.8 부터 hook 을 지원함. Hook을 사용하면 개발자는 컴포넌트로부터 상태 관련 로직을 추상화할 수 있습니다. 이를 이용해 독립적인 테스트와 재사용이 가능합니다. Hook은 계층의 변화 없이 상태 관련 로직을 재사용할 수 있도록 도와줍니다. 이것은 많은 컴포넌트 혹은 사이에서 Hook을 통해 상태와 정보를 공유하기 쉽게 만들어줍니다.


Grapqhql-hooks 는 react 에서 hook 기반의 graphql resolver(Query, Mutation) 함수를 사용할 수 있도록 도와줍니다.


기본 적인 사용법은 graphql-hooks github 를 참고하기 바랍니다.


본 장에서는 graqph-hooks 사용시, 자동 리렌더링을 위한 방법에 대하여 알아 보도록 한다. 일반적으로 hooks 을 사용하여 자동 리렌더링을 사용시에는 useEffect() 를 활용하여 state 변수의 변화에 따라 fetchAPI() 를 콜하고, state 를 업데이트 함으로써 하위의 컴포넌트들의 데이터가 업데이트될 수 있도록 한다. 하지만 graphql-hooks 는 useEffect() 함수 내에서 콜이 될 수 없기 때문에, 기존 방식을 통한 자동 리렌더링이 불가능 함.


useEffect() 와 fetechAPI() 를 활용한 자동 리렌더링의 예제 코드

function CustomerListView() {
 const classes = useStyles();
 const isMountedRef = useIsMountedRef();
 const [customers, setCustomers] = useState(null);

 const getCustomers = useCallback(() => {
 axios
      .get('/api/management/customers')
      .then((response) => {
 if (isMountedRef.current) {
 setCustomers(response.data.customers);
        }
      });
  }, [isMountedRef]);

 useEffect(() => {
 getCustomers();
  }, [getCustomers]);

 if (!customers) {
 return null;
  }

 return  ...

이를 위해, 우리는 useEffect, context, graphql-hooks 의 refetchAPI() 를 사용하는 방안을 설명한다. context 는 react 에서 전역 state 를 관리하는 모듈로써, context 로 정의되고 wrapping 된 컴포넌트들은 언제 어디서든 context 의 state 변화에 따른 모든 컴포넌트와의 상태 공유가 가능해 진다. 이를 활용하는 예는, Language 옵션, Polling 주기 옵션 등이 있다. 우리는 이를 활용해서 리렌더링이 필요한 경우의 context state 를 정의하고 해당 state 의 변화시 useEffect 를 통해 graphql-hooks 의 refetchAPI() 를 콜 하여 리렌더링을 관리하도록 한다.


context 와 graphql-hooks 의 refetchAPI() 를 활용한 자동 리렌더일 예제



function AlarmDetailsView() {
 const classes = useStyles();
 let { alarmId } = useParams();
 const { settings } = useSettings();
 const { loading, error, data, refetch } = useQuery(util.format(QueryMapperRanges[settings.duration], alarmId));
 const failoverResp = useQuery(util.format(FailoverQueryMapperRanges[settings.duration], alarmId));
 
 let alarm = data;
 let failovers = failoverResp.data;

 // Timer based refresh module
 useEffect(() => {
 refetch();
 failoverResp.refetch();
  }, [settings.refreshTick]);

 if (loading || failoverResp.loading) return <SplashScreenResult />;
 ...

const { loading, error, data, refetch } = useQuery() 의 refetch 는 graphql Query 의 refetch 함수 모듈로써, refetch() 를 call 할 경우, { loading, error, data } 의 state 값이 업데이트가 되어 하부 컴포넌트들로 변화가 전파되게 된다.


useEffect() 는 이런 refetch() 를 콜해서, 특정 전역 상태 값의 변화에 따른 컴포넌트의 life-cycle 을 관리할 수 있게 되고, 상기 코드의 경우는 settings.refreshTick state 와 같이 리렌더링이 필요한 경우, refetch() 함수를 콜해서 리렌더링이될 수 있도록 한다.