티스토리 뷰

728x90
반응형

useCallback



useCallback 은 함수를 최적화하기 위해 사용하는 hook 으로, useMemo 와 비슷하다.

useMemo 는 함수를 값처럼 사용해서 연산 최적화를 하기위해 사용한다면, useCallback 은 특정 함수를 재정의(새로 만들지 않고) 하지 않고 재사용 하기위해 사용한다. 



useCallback 이 필요한 이유 !!



React.memo 는 컴포넌트에서 전달된 prop 이 변경될 때만 랜더링 되도록 도와주는 함수이다.

그러나, 전달된 prop 이 '값' (Promitive type) 이 아니라 '객체' 나 '함수' (Reference type) 일 경우엔 얕은 비교를 하기 때문에 안에 내용이 같더라도 변경되었다고 간주하여 컴포넌트를 리랜더링 하는 경우가 있다.

import React, { useCallback, useEffect, useRef, useState } from "react";
import "./styles.css";

const ComponentA = ({ data, deleteData }) => {
  useEffect(() => {
    console.log("ComponentA is render");
  });

  return (
    <div>
      {data.map((it) => (
        <div>
          <div>{it.id}</div>
          <button
            onClick={() => {
              deleteData(it.id);
            }}
          >
            삭제
          </button>
        </div>
      ))}
    </div>
  );
};

//React.memo 전달된 prop이 변경될 때만 랜더링
const ComponentB = React.memo(({ createData }) => { 
  useEffect(() => {
    console.log("ComponentB is render");
  });

  return (
    <div>
      <button onClick={createData}>데이터 삽입</button>
    </div>
  );
});

export default function App() {
  const [data, setData] = useState([]);
  const num = useRef(0);

  const createData = () => {
    num.current++;
    setData([...data, { id: num.current }]);
  };

  const deleteData = (id) => {
    setData(data.filter((it) => it.id != id));
  };
  return (
    <div className="App">
      <ComponentA data={data} deleteData={deleteData} />
      <ComponentB createData={createData} />
    </div>
  );
}​

위에서, App 컴포넌트의 data state 는 ComponentB의 button(데이터 삽입) 을 누르게 되면 변경이되어 App 컴포넌트를 리랜더링 한다.

그 과정에서, createData 함수를 재선언하게 되는데, 이 때, createData 함수가 reference type 이므로 ComponentB 에서 createData 함수가 변경되었다고 판단하여 ComponentB를 리랜더링하게 된다.

그러므로, App 컴포넌트가 랜더링 될 때, createData 함수가 재선언되지 않도록 만들어야 하는데, 이 때 사용하는 것이 useCallback hook 이다 !!



useCallback 사용



함수가 재선언되지 않게, 최적화를 하기 위해서  함수를 useCallback을 사용하여 감싸준다.

import React, { useCallback, useEffect, useRef, useState } from "react";
import "./styles.css";

const ComponentA = ({ data, deleteData }) => {
  useEffect(() => {
    console.log("ComponentA is render");
  });

  return (
    <div>
      {data.map((it) => (
        <div>
          <div>{it.id}</div>
          <button
            onClick={() => {
              deleteData(it.id);
            }}
          >
            삭제
          </button>
        </div>
      ))}
    </div>
  );
};

//React.memo 전달된 prop이 변경될 때만 랜더링
const ComponentB = React.memo(({ createData }) => {
  useEffect(() => {
    console.log("ComponentB is render");
  });

  return (
    <div>
      <button onClick={createData}>데이터 삽입</button>
    </div>
  );
});

export default function App() {
  const [data, setData] = useState([]);
  const num = useRef(0);

  const createData = useCallback(() => {
    num.current++;
    setData((data) => [...data, { id: num.current }]);
  }, []);

  // const createData = () => {
  //   num.current++;
  //   setData([...data, { id: num.current }]);
  // };

  const deleteData = (id) => {
    setData(data.filter((it) => it.id != id));
  };
  return (
    <div className="App">
      <ComponentA data={data} deleteData={deleteData} />
      <ComponentB createData={createData} />
    </div>
  );
}

useCallback 을 사용할 때 , 2번째 인자에 defendency array 를 넘기고, setData 로 state를 초기화 해줄 때, 함수형 업데이트로 초기화를 해주어야 한다.

함수형 업데이트로 초기화를 해주어야, defenden array를 비워도 항상 최신의 state를 함수형 업데이트의 인자를 통해서 참조할 수 있게 된다.



참고



https://espania.tistory.com/366
 

[React] 최적화 / 컴포넌트 재사용 / React.memo

비효율적인 컴포넌트 rendering setCount(10); setText("Hello"); App 컴포넌트 의 count state를 setCount로 변경하게 되면, App 컴포넌트가 랜더링 되고 자식 컴포넌트 들인 CountView 컴포넌트와 TextView 컴..

espania.tistory.com

https://espania.tistory.com/367

 

[React] 최적화 / 함수 재사용 / memoization / useMemo

Memoization 이미 계산 해 본 연산 결과를 기억 해 두었다가 동일한 계산을 시키면, 다시 연산하지 않고, 기억 해두 었던 데이터 를 반환 시키게 하는 방법 useMemo export default function App() { const data..

espania.tistory.com

https://codesandbox.io/s/romantic-violet-vx9erh?file=/src/App.js:0-1311 

 

romantic-violet-vx9erh - CodeSandbox

romantic-violet-vx9erh by jins4731 using react, react-dom, react-scripts

codesandbox.io

728x90
댓글
반응형
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함