[React] useMemo / useCallback

현수·2022년 4월 26일
0

면접준비

목록 보기
8/10

useMemo / useCallback을 알아보기에 앞서 알아야하는 것

  • 함수형 컴포넌트 또한 jsx를 반환하는 함수이다.
  • 컴포넌트가 렌더링 된다는 것은 그 함수(컴포넌트)가 호출되어 실행된 것이며, 함수가 실행될 때마다 내부에 선언되어 변수나 다른 함수들도 매번 다시 선언되어 사용된다.
  • 컴포넌트는 자신의 state가 변경되거나, 부모에게서 받는 props가 변경될 때마다 리렌더링 되며, 하위 컴포넌트는 최적화 설정을 해주지 않으면 부모에게서 받는 props가 변경되지 않았더라도 리렌더링 되는 것이 기본이다.


useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • 메모이제이션 된 값을 반환하는 훅.
  • 리렌더링이 되더라도 특정 값이 다시 연산될 필요가 없을 경우, 그 값을 메모이제이션 해뒀다가 사용할 수 있다. (최적화)
// 부모 컴포넌트
const App = () => {
  const [color, setColor] = useState("");
  const [movie, setMovie] = useState("");

  const onChangeHandler = e => {
    if (e.target.id === "color") setColor(e.target.value);
    else setMovie(e.target.value);
  };

  return (
    <div className="App">
      <div>
        <label>
          What is your favorite color of rainbow ?
          <input id="color" value={color} onChange={onChangeHandler} />
        </label>
      </div>
      <div>
        What is your favorite movie among these ?
        <label>
          <input
            type="radio"
            name="movie"
            value="Marriage Story"
            onChange={onChangeHandler}
          />
          Marriage Story
        </label>
        <label>
          <input
            type="radio"
            name="movie"
            value="The Fast And The Furious"
            onChange={onChangeHandler}
          />
          The Fast And The Furious
        </label>
        <label>
          <input
            type="radio"
            name="movie"
            value="Avengers"
            onChange={onChangeHandler}
          />
          Avengers
        </label>
      </div>
      <Info color={color} movie={movie} />
    </div>
  );
};
// 자식 컴포넌트
const getColorKor = color => {
    console.log("getColorKor");
    switch (color) {
      case "red":
        return "빨강";
      case "orange":
        return "주황";
      case "yellow":
        return "노랑";
      case "green":
        return "초록";
      case "blue":
        return "파랑";
      case "navy":
        return "남";
      case "purple":
        return "보라";
      default:
        return "레인보우";
    }
  };

  const getMovieGenreKor = movie => {
    console.log("getMovieGenreKor");
    switch (movie) {
      case "Marriage Story":
        return "드라마";
      case "The Fast And The Furious":
        return "액션";
      case "Avengers":
        return "슈퍼히어로";
      default:
        return "아직 잘 모름";
    }
  };


const Info = ({ color, movie }) => {
  const colorKor = getColorKor(color);
  const movieGenreKor = getMovieGenreKor(movie);

  return (
    <div className="info-wrapper">
      제가 가장 좋아하는 색은 {colorKor} 이고, <br />
      즐겨보는 영화 장르는 {movieGenreKor} 입니다.
    </div>
  );
};

  • 위 상황의 경우 자식 컴포넌트로 colormovie가 props로 전달되는데, 이 때 color의 값만 변경되더라도 colorKor뿐만 아니라 movieGenreKor 함수까지 다시 연산된다.
const colorKor = useMemo(() => getColorKor(color), [color]);
const movieGenreKor = useMemo(() => getMovieGenreKor(movie), [movie]);
  • 위와 같이 useMemo를 사용하면 각 함수는 연산한 값을 메모이제이션하게 되고, 의존성 배열에 있는 값이 변경되었을 때만 다시 연산을 실행하게 된다.


useCallback

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);
  • 메모이제이션 된 콜백(함수)을 반환하는 훅.
  • 리렌더링이 되더라도 특정 함수가 매번 다시 선언될 필요가 없을 경우, 그 함수를 메모이제이션 해뒀다가 사용할 수 있다. (최적화)
const onChangeHandler = useCallback(e => {
    if (e.target.id === "color") setColor(e.target.value);
    else setMovie(e.target.value);
  }, []);
  • 위의 예제 상황에서 onChangeHandler는 한 번 선언되고나면 또 다시 선언될 필요가 없으므로, useCallback으로 메모이제이션해두고 사용할 수 있다.
  • 공식문서에 의하면 콜백을 최적화된 자식컴포넌트에 props로 넘길 때 유용하게 사용할 수 있다.
    • 어떤 함수와 완전히 같은 함수는 현재 그 함수 뿐이기 때문에, (memo로 자식컴포넌트가 최적화되었을 때) 전달되는 함수가 다시 선언될 경우 그 함수가 완전히 이전과 같더라도 다른 것으로 취급하고 props가 변경된 것으로 인식해 리렌더링 된다.
  • useCallback(fn, deps)은 useMemo(() => fn, deps)와 같다.


profile
언젠간 되겠지!

0개의 댓글