✔ Memoized value를 리턴하는 훅.
✔ 연산량이 높은 작업이 매번 렌더링될 때마다 반복되는 것을 피하기 위해 사용.
✔ 렌더링이 일어나는 동안 실행.
✔ const memoizedValue = useMemo(값 생성 함수, 의존성 배열);
✔ 의존성 배열에 들어있는 변수가 변했을 경우에만 새로 값 생성 함수를 호출하여 결괏값을 반환.
✔ 의존성 배열이 없을 경우 렌더링이 일어날 때마다 매번 값 생성 함수가 실행되므로 useMemo()를 사용하는 의미가 없음.
import { useMemo, useState } from "react";
function ExUseMemo() {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const increment = () => {
setCount(c => c + 1);
};
const addTodo = () => {
setTodos(t => [...t, "New Todo"]);
};
const expensiveCalculation = (num) => {
console.log("Calculating...");
for (let i = 0; i < 1000000; i++) {
num += 1;
}
return num;
};
const calculation = expensiveCalculation(count);
return (
<div>
<div>
<h2>My Todos</h2>
{todos.map((todo, index) => {
return <p key={index}>{todo}</p>;
})}
<button onClick={addTodo}>Add Todo</button>
</div>
<hr />
<div>
Count: {count}
<button onClick={increment}>+</button>
<h2>Expensive Calculation</h2>
{calculation}
</div>
</div>
);
}
export default ExUseMemo;
출처 W3Schools
위 예제는 'Add Todo' 를 클릭할 때 마다 리렌더링 되면서 count 값이 변하지 않음에도 콘솔에 "Calculating..." 이 출력되고 계산량이 큰 for문도 매번 의미없는 작업을 하게 된다. 이를 방지하기 위해 useMemo()를 활용한다.
const calculation = expensiveCalculation(count);
해당 부분을 아래와 같이 변경한다.
const calculation = useMemo(() => expensiveCalculation(count), [count]);
calculation은 이제 렌더링이 될 때 마다 의존성 배열의 count를 이전 count 값과 비교한다. count가 변경되지 않았으면 계산을 거치지 않고 기억했던 이전 값을 그대로 반환하고, 변경이 되었을 땐 expensiveCalculation() 함수를 재계산하여 count의 값을 반환한다. 'Add Todo' 를 클릭해도 콘솔에는 "Calculating..." 이 출력되지 않으며, 의미없는 for문 작업도 하지 않는다.
✔ 위의 예제처럼 식의 부하가 크고, 자주 바뀌지 않는 값에 사용하는 것이 유용.
✔ Chrome에 React Developer Tools 프로파일러를 참고하여 시간이 오래 걸리는 코드를 찾고 필요한 경우 사용하는 것을 추천.