✅ useMemo
- 함수 컴포넌트 내부에서 발생하는 연산 최적화
- 복잡한(꼭 그렇지만은 않더라도) 연산이 직접적 관계 없는 값에 의한 재렌더링으로 계속해서 실행되는 비효율을 막을 수 있음
...
const [input, setInput] = useState('');
const [numList, setNumList] = useState([])
const getPlus = (numbers) => {
let defaultNum = 0;
const sum = numbers.map((num) => defaultNum + num);
return sum;
}
const onChange = (e) => {
setInput(e.target.value);
}
const onClick = () => {
let nums = [...numList, parseInt(input)]
setNumList(nums);
setInput('');
}
...
return (
<div>
<input value = {inputNum} onChange = {onChange} />
<button onClick = {onClick}>Plus</button>
<div>합계 : {getPlus(numList)}</div>
</div>
)
// ❗️input에 의해 재렌더링이 일어날 때마다 합계인 getPlus(numList)가 재실행!!
// 윗부분 동일
...
const plusNum = useMemo(() => getPlus(numList), [numList])
return (
<div>
<input value = {inputNum} onChange = {onChange} />
<button onClick = {onClick}>Plus</button>
<div>합계 : {plusNum}</div>
</div>
)
✅ useCallback
- useMemo와 유사
- 주로 렌더링 성능을 최적화해야 하는 상황에서 사용
- 앞선 코드를 다시 보면
...
const [input, setInput] = useState('');
const [numList, setNumList] = useState([])
const getPlus = (numbers) => {
let defaultNum = 0;
const sum = numbers.map((num) => defaultNum + num);
return sum;
}
const onChange = (e) => {
setInput(e.target.value);
}
const onClick = () => {
let nums = [...numList, parseInt(input)]
setNumList(nums);
setInput('');
}
const plusNum = useMemo(() => getPlus(numList), [numList])
return (
<div>
<input value = {inputNum} onChange = {onChange} />
<button onClick = {onClick}>Plus</button>
<div>합계 : {plusNum}</div>
</div>
)
- 페이지 재렌더링이 일어날 때마다 onChagne와 onClick 함수가 계속해서 재선언됨
=> 재렌더링이 자주 발생하거나 컴포넌트의 개수가 많아지면 최적화 해주는 게 좋음
=> useCallback 사용!!
const onChange = useCallback(
(e) => {
setInput(e.target.value);
}, []
)
const onClick = useCallback(
() => {
let nums = [...numList, parseInt(input)]
setNumList(nums);
setInput('');
}, [input, numList]
)
- 첫 번째 파라미터에는 생성하고 싶은 함수를, 두 번째 파라미에는 어떤 값이 바뀌었을 때 새로 생성해야 하는지 명시하는 배열을 넣음
- 의존성 배열을 비워두면 처음 페이지가 렌더링 될 때 만들어진 함수를 계속해서 재사용