예전에 달력을 직접 만들어보면서 달력의 상위 컴포넌트 중에 input의 값이 변경될 때마다 하위 컴포넌트인 달력 컴포넌트가 계속된 불필요한 계산으로 느려진 현상이 있었다.
이를 해결하기 위해 useMemo를 사용하여 달력의 좌우버튼을 클릭하여 달이 바뀔 때에만 새롭게 계산될 수 있도록 구현함으로써 해결
할 수 있었다.
import ReactDOM from 'react-dom';
import React, { useState, useMemo } from 'react'
const NameLength = () => {
const [nickname, setNickname] = useState('')
const nicknameLength = useMemo(() => nickname.length, [nickname]);
const updateNickname = event => {
const nickname = event.target.value
setNickname(nickname)
}
return (
<div>
<input onChange={updateNickname} />
<br/>
<label>{nicknameLength}</label>
</div>
)
}
ReactDOM.render(<NameLength />, document.getElementById('root'));
nickname이라 변수를 의존성으로 전달하여 nickname이 변경되었을 때만 값을 다시 계산하도록 코드를 작성하였다.
useCallback의 경우에도 상위 컴포넌트에서 하위 컴포넌트로 함수를 전달하는 과정에서 함수를 새롭게 생성해서 보내주어 불필요한 리렌더링을 하고 있어서 이를 해결하려고 사용했던 적이 있었다.
import ReactDOM from 'react-dom';
import React, { useCallback, useState, useMemo } from 'react'
const SumString = () => {
const [string, setString] = useState('');
const [stringList, setStringList] = useState([]);
const change = useCallback((e) => {
setString(e.target.value);
}, []);
const insert = useCallback(() => {
const newList = stringList.slice();
newList.push(string);
setStringList(newList);
}, [string, stringList]);
const sum = useCallback((list) => {
let stringSum = '';
for(let i = 0; i < list.length; i++){
stringSum += list[i] + ' ';
}
return stringSum;
}, []);
const result = useMemo(() => sum(stringList), [stringList, sum]);
return (
<div>
<input type='text' onChange={change}/>
<button onClick={insert}>문자열 붙이기</button>
<br/>
{result}
</div>
)
}
ReactDOM.render(<SumString />, document.getElementById('root'));
위의 코드에서 sum의 함수의 경우 useCallback을 사용하지 함수일 경우 input값에 value가 변경될때마다 해당 컴포넌트가 다시 렌더링하기 때문에 적힌 수만큼 sum 함수가 호출되는 것을 볼 수 있다.
const sum = (list) => {
console.log('NoneUseCallback innerSum');
let stringSum = '';
for(let i = 0; i < list.length; i++){
stringSum += list[i] + ' ';
}
return stringSum;
}
하지만 useCallback을 사용한다면 처음 렌더링 했을 때만 호출되는 것을 확인 할 수 있다.
const sum = useCallback((list) => {
console.log('innerSum');
let stringSum = '';
for(let i = 0; i < list.length; i++){
stringSum += list[i] + ' ';
}
return stringSum;
}, []);