useCallback은 useMemo와 비슷한 함수입니다.
주로 랜더링 성능을 최적화해야 하는 상황에서 사용하는데, 만들어 놨던 함수를 재사용
할 수 있습니다.
// 리스트에 숫자를 추가하면 추가된 숫자들의 평균을 보여수는 함수형 컴포넌트
import { useState, useMemo, useCallback } from 'react';
const getAverage = numbers => {
// 평균 값 구하는 함수
console.log('평균값 계산 중...');
if(numbers.length === 0) return 0;
const sum = numbers.reduce((a, b) => a + b);
return sum / numbers.length;
};
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState('');
const onChange = useCallback(e => {
setNumber(e.target.value);
}, []); // 컴포넌트가 처음 랜더링될 때만 함수 생성
const onInsert = useCallback(e => {
const nextList = list.concat(parsInt(number));
setList(nextList);
setNumber('');
}, [number, list]); // number 또는 list 가 바뀌었을 때만 함수 생성
const avg = useMemo(() => getAverage(list), [list]);
return(
<div>
<input value={number} onChange={onchange} />
<button onClick={onInsert}>등록</button>
<ul>
{
list.map((value, index) => (
<li key={index}>{ value }</li>
))
}
</ul>
<div>
<b>평균값 : </b> { avg }
</div>
</div>
)
}
export default Average;
useMemo를 다룬 게시글에서 사용했던 onChange와 onINsert라는 함수는 컴포넌트가 리렌더링될 때마다 새로 만들어진 함수를 사용하게 됩니다. 대부분의 경우 이러한 방식은 문제가 없지만, 컴포넌트의 렌더링이 자주 발생하거나 렌더링해야 할 컴포넌트의 개수가 많아지면 최적화해 주는 것이 좋습니다.
useCallback의 첫 번째 파라미터
에는 생성하고 싶은 함수를 넣고, 두 번째 파라미터
에는 배열을 넣으면 됩니다. 이 배열에는 어떤 값이 바뀌었을 때 함수를 새로 생성해야 하는지 명시해야 합니다.
onChange처럼 비어 있는 배열을 넣게 되면 컴포넌트가 렌더링될 때 만들었던 함수를 계속해서 재사용하게 되며 onInsert처럼 배열 안에 number와 list를 넣게 되면 input내용이 바뀌거나 새로운 항목이 추가될 때 새로 만들어진 함수를 사용하게 됩니다.