React - useMemo()

gyu0714·2022년 11월 7일
0

Hooks

목록 보기
5/9
post-thumbnail

useMemo()

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

메모이제이션 된 값을 반환한다.
"생성(create)" 함수와 그것의 의존성 값의 배열을 전달한다. useMemo는 의존성이 변경되었을 때에만 메모이제이션된 값만 다시 계산한다. 이 최적화는 모든 렌더링 시의 고비용 계산을 방지하게 해준다.

useMemo로 전달된 함수는 렌더링 중에 실행된다. 통상적으로 렌더링 중에 하지 않는 것을 이 함수 내에서 해서는 안된다. 예를 들어, 사이트 이펙트(side effect)는 useEffect에서 하는 일이지 useMemo에서 하는 일이 아니다.

deps가 없는 경우 매 렌더링 때 마다 새 값을 계산하게 될 것이다.

useMemo는 성능 최적화를 위해 사용할 수는 있지만 의미상으로 보장이 있다고 생각해서는 안된다.

  • 메모이제이션을 다시 계산할 필요가 없도록 값을 캐싱하는 것이다.
  • useMemo는 useCallback과 비슷하다. 주요 차이점은 메모화 useMemo된 값을 useCallback으로 반환하고 메모화된 함수를 반환한다는 것이다.

성능

Hook은 useMemo 값 비싼 리소스 집약적인 기능이 불필요하게 실행되지 않도록 하는데 사용할 수 있다.

import { useState } from "react";
import ReactDOM from "react-dom/client";

const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  const calculation = expensiveCalculation(count);

  const increment = () => {
    setCount((c) => c + 1);
  };
  const addTodo = () => {
    setTodos((t) => [...t, "New Todo"]);
  };

  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>
  );
};

const expensiveCalculation = (num) => {
  console.log("Calculating...");
  for (let i = 0; i < 1000000000; i++) {
    num += 1;
  }
  return num;
};

성능이 좋지 않은 예이다. expensiveCalculation 함수는 모든 렌더링에서 실행된다.

useMemo 사용 시

useMemo를 사용하여 expensiveCalculation 함수를 메모할 수 있다. 이렇게 하면 필요할 때만 함수가 실행된다. useMemo는 종속성을 선언하기 위해 두 번째 매개변수를 허용한다. 함수는 종속성이 변경된 경우에만 실행된다. expensiveCalculation 함수는 count가 변경 될 때만 실행되고 할 일을 추가 할 때는 실행되지 않는다.

import { useState, useMemo } from "react";
import ReactDOM from "react-dom/client";

const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  const calculation = useMemo(() => expensiveCalculation(count), [count]);

  const increment = () => {
    setCount((c) => c + 1);
  };
  const addTodo = () => {
    setTodos((t) => [...t, "New Todo"]);
  };

  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>
  );
};

const expensiveCalculation = (num) => {
  console.log("Calculating...");
  for (let i = 0; i < 1000000000; i++) {
    num += 1;
  }
  return num;
};
profile
gyu0714

0개의 댓글