dukDukz

[React] useCallback - 함수 재사용하기 본문

웹 개발/React

[React] useCallback - 함수 재사용하기

헤일리_HJ 2022. 1. 27. 14:28

useCallback은 useMemo 와 비슷한 훅이다.

 

useMemo 는 특정 결과값을 재사용 할 때 사용하는 반면, useCallback 은 특정 함수를 새로 만들지 않고 재사용하고 싶을때 사용합니다.

 

컴포넌트에 함수를 선언하면 컴포넌트가 리렌더링 될 때마다 새로 만들어진다.

크게 리소스를 낭비하지는 않지만, useCallback을 어떻게 쓸지는 알아놔야 한다.

 

컴포넌트에서 props 가 바뀌지 않았으면 Virtual DOM 에 새로 렌더링하는 것 조차 하지 않고 컴포넌트의 결과물을 재사용 하는 최적화 작업을 할건데요, 이 작업을 하려면, 함수를 재사용하는것이 필수입니다.

 

 

 

 

App.js

 

import React, { useState, useCallback } from "react";
import List from "./List";

export default function App() {
  const [number, setNumber] = useState(1);
  const [dark, setDark] = useState(false);

  // useMemo 와 다른 점은 얘는 함수 전체를 return 하고 인자값도 받을 수 있다.
  // only recreated getItems function when number changed
  const getItems = useCallback(() => {
    return [number, number + 1, number + 2];
  }, [number]);

  const theme = {
    backgroundColor: dark ? "#333" : "#FFF",
    color: dark ? "#FFF" : "#333"
  };

  return (
    <div className="App" style={theme}>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(parseInt(e.target.value))}
      />

      <button onClick={() => setDark((prevDark) => !prevDark)}>
        Toggle theme
      </button>
      <List getItems={getItems} />
    </div>
  );
}

 

 

여기서 잘 봐야 할 부분은 getItems 함수를 useCallback으로 썼다는 것이다.

 

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

export default function List({ getItems }) {
  const [items, setItems] = useState([]);

  useEffect(() => {
    setItems(getItems());
    console.log("updating items");
  }, [getItems]);

  return items.map((item) => <div key={item}>{item}</div>);
}

 

 

 

useCallback 이 아닌 그냥 함수로 사용했을 때는 컴포넌트가 리렌더링 될때마다 새로 만들어진다.

여기서 dark 라는 state를 useState로 관리해주기 때문에 상태가 변할 때 마다 리렌더링 되기 때문에 

그때마다 getItems 라는 함수를 새로 선언해주게 된다.

그래서 updating items라는 콘솔이 숫자를 변경할때, 토글 버튼을 눌렀을 때 

두번 다 찍히게 되는 것이다.

 

이를 useCallback으로 바꿔주면

 

  const getItems = useCallback(() => {
    return [number, number + 1, number + 2];
  }, [number]);

  useMemo 와 다른 점은 얘는 함수 전체를 return 하고 인자값도 받을 수 있다.
  only recreated when "number" changed

 

number를 배열안에 넣어주면 해당 값이 변할 때만 이 함수를 다시 써주겠다고 하는 것이다.

 

그래서 이제는 number 의 state가 변했을 때만 함수를 다시 써주게 되어 

토글 버튼을 눌러도 저 콘솔이 찍히지 않게된다.