컨테이너 + 프레젠테이션 구조로 리액트 앱을 짜면, 컨테이너 컴포넌트에서 Hook을 통해 state를 관리한다.
이번에는 React Hook의 기초 내용을 이해하게 해준 '얼마나 남았나' 를 표기해주는 info 파트의 제작일지이다.
버스 카드 내에 있는 '얼마나 남았나'를 보여주는 문구의 갱신 setBusTime() 함수는 세 가지 상황에 호출되어야 한다.
제작 과정은 이러했다.
실제 동작은 이러했다.
setInterval함수를 컨테이너 밖으로 꺼낸다 하더라도 매 렌더링은 고유의 값들을 가지므로 destroyed, 즉 componentWillUnmount에 clearInterval을 넣어야 하므로 이 과정을 통합하여 custom Hook을 이용했다.
import React, { useRef, useEffect } from "react"
useInterval(() => {
setBusTime(params);
},1000)
//hoisting
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest function.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
이제 실행을 했을 때, 다음 문제가 발생했다. 현재 useEffect의 상태를 보자.
useEffect(() => {
setBusTime(params);
})
매 초마다 useInterval()에 의해 setBusTime()이 실행되지만, setBusTime()에 의해 화면이 재 렌더링되면서 useEffect에 의해 한번 더 setBusTime이 호출된다.
그렇기에 useEffect에 의존성을 부여할 필요가 생긴다. setBusTime은 렌더링될 때, departList와 arrivalList가 바뀔 때만 호출되어야한다.
useEffect(() => {
setBusTime(params);
}, [departList, arrivalList]);
이제 setBusTime은 알맞게 호출된다.
useEffect에 의해 렌더링될 때 호출,
useInterval에 의해 매 초마다 호출,
드롭다운에 의해 departList와 arrivalList가 바뀔 때마다 useEffect에 의해 호출.