봐도 봐도 정리가 안 되고 헷갈렸던 Hooks들에 대해서 혼자 찾아보고 정리한 글입니다.
리액트를 다루는 기술 [개정판] (김민준, 길벗출판사)
책과 ZeroCho님의 사이트에 있는 설명과 예제를 참고했습니다. 😇
useState는 state를 추가해주는 Hook입니다. state는 화면 렌더링과 관련된 (변경되는) 데이터를 다룰 때 쓰입니다. 이는 곧 state를 바꾸면 컴포넌트가 리렌더링된다는 것을 의미합니다.
// 기본 형태
const [상태, 상태변경함수] = useState(초깃값);
const [hidden, setHidden] = useState(false);
useCallback은 함수를 캐싱(또는 메모이제이션)할 때 사용하는 Hook입니다. 컴포넌트의 렌더링 성능을 최적화할 때 활용합니다.
두 번째 파라미터 값으로 들어가는 deps(dependencylist) 배열이 비어있으면 컴포넌트가 렌더링 될 때 만들었던 함수를 계속 재사용합니다.
deps에 특정한 값이 있으면 그 값이 바뀔 때마다 함수를 새로 만들어 캐싱합니다.
deps는 여러 개의 값을 가질 수 있고 useCallback은 이 값들을 계속 추적하면서 값이 바뀌는지 확인합니다.
메모이제이션이란?
메모이제이션(memoization)은 컴퓨터 프로그램이 동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술이다
const onClickButton = useCallback(() => {
setHidden(true);
}, []);
useMemo는 컴포넌트 내부에서 발생하는 연산을 최적화할 때 사용되는 Hook입니다. 렌더링하는 과정에서 특정 값이 바뀌었을 때만 연산을 실행하고 원하는 값이 바뀌지 않았다면 이전에 연산했던 결과를 다시 사용합니다.
useCallback과 마찬가지로 deps 배열이 존재하며 deps 배열 내부의 값이 달라지면 기존 캐싱된 것을 버리고 새로 값을 구하는 방식으로 실행됩니다.
const Basic = () => {
const cachedNumbers = useMemo(() => getWinNumbers(), []);
const [lottoNumbers, setLottoNumbers] = useState(cachedNumbers);
return <div>{lottoNumbers.join(',')}</div>;
};
위의 코드의 경우 Basic 컴포넌트가 리렌더링되더라도 getWinNumbers가 다시 호출되지 않아 렌더링 성능을 최적화할 수 있습니다.
useCallback(() => {}, []);
useMemo(() => 값, []);
ref는 DOM 노드나 React 엘리먼트에 접근하는 방법을 제공합니다. useRef는 함수형 컴포넌트에서 ref를 쉽게 사용할 수 있도록 해주는 Hook입니다. (HTML의 id와 유사한 기능)
화면 리렌더링과 관련이 없는 컴포넌트 로컬 변수를 사용해야 할 때도 활용할 수 있습니다.
useEffect는 클래스형 컴포넌트의 라이프사이클을 대체하는 Hook으로 리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행할 수 있도록 설정할 수 있습니다.
뒷정리(cleanup) 함수를 return하면 컴포넌트가 언마운트되기 전에 지정한 작업을 수행할 수도 있습니다. (class형 컴포넌트에서 componentWillUnmount의 역할)
클래스형 컴포넌트의 라이프사이클과 다르게 컴포넌트 중심이 아닌 데이터 중심으로 실행됩니다.
useEffect(() => {
console.log('hidden changed');
}, [hidden]);
(1) 위 코드는 컴포넌트가 첫 렌더링될 때 한 번 실행되고 hidden이라는 값이 바뀔 때마다 실행됩니다. (class형 컴포넌트에서 componentDidMount와 componentDidUpdate가 합쳐진 형태)
useEffect(() => {
console.log('mounted');
return () => {
console.log('unmount');
}
}, []);
(2) 마운트 될 때 처음 한 번만 실행하는 코드입니다.
useEffect(() => {
console.log('rerendered!');
});
(3) deps가 아예 주어지지 않은 상황으로 컴포넌트가 리렌더링 될 때마다 실행합니다.
useEffect(() => {
console.log('hidden changed');
return () => {
console.log('hidden이 바뀔 예정입니다.');
};
}, [hidden]);
(4) 클린업 함수를 작성하면 componentWillUnmount의 역할도 담당할 수 있습니다.
useEffect가 클래스형 컴포넌트의 라이프사이클 메소드들과 연관되지 않아서 가장 이해하기 힘들고 헷갈렸는데 천천히 정리하고 나니 많이 도움이 됐다... 아직 활용 쪽에서는 실력이 부족하지만 계속해서 공부하면 언젠간 마스터할 수 있을 거라고 믿는다. 😼