DarrenKwonDev 2020. 7. 5. 22:33

공시 홈페이지에서 딱히 예제를 보여주고 있지 않습니다.

 

Returns a memoized value.

 

Pass a “create” function and an array of dependencies. useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render.

 

 

컴포넌트 내부에서 발생하는 연산을 최적화하는데 사용한다고 합니다. 최적화라는 관점에서 useCallback, useMemo가 사용된다고 보시면 됩니다.

 

useMemo가 컴포넌트 내부에서 진행되는 연산을 최적화한다면 useCallback은 컴포넌트 내부에 정의된 이벤트 핸들러들을 필요할 때만 렌더하도록 만들어 최적화할 수 있습니다.

 

두 훅은 서로 호환되게 만들 수도 있습니다만 굳이 그렇게 할 실익은 없습니다. 

 

다음과 같이 input을 받아서 평균을 계산하는 함수를 돌린다고 가정합시다.

import React, { useMemo, useState } from "react";

// numbers 배열을 받아서 평균을 리턴하는 함수
const getAverage = (numbers) => {
  console.log("평균값을 계산합니다");
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
};

const App = () => {
  const [list, setlist] = useState([]);
  const [number, setnumber] = useState("");

  const onChange = (e) => {
    setnumber(e.target.value);
  };

  const onInsert = (e) => {
    // 배열에 직접 추가하지 말고 concat을 통해 새 배열을 만들어줘야 합니다!!
    const nextList = list.concat(parseInt(number));
    setlist(nextList);
    setnumber("");
  };

  return (
    <>
      <div>
        <input value={number} onChange={onChange}></input>
        <button onClick={onInsert}>등록</button>
        <ul>
          {list.map((value, index) => (
            <li key={index}>{value}</li>
          ))}
        </ul>
      </div>
      // 컴포넌트 내부에서 사용하는 연산이 있네요! useMemo의 대상입니다
      <div>평균값 : {getAverage(list)}</div>
    </>
  );
};

export default App;

 

작동은 잘 합니다. 문제는, 단순히 input값을 바꿨을 뿐 제출하지는 않았을 때에도 getAverage 함수가 호출된다는 것입니다.

 

해당 함수를 useMemo로 감싼 후, list값이 변화했을 때만 연산을 하도록 만들었습니다.

막상 코드를 치고 보니 공식 문서랑 똑같네요;; useCallback을 사용하는 방법과도 똑같습니다!

const avg = useMemo(() => getAverage(list), [list]);