여러분이 사용하고 계신 브라우저는 HTML5를 지원하지 않기 때문에 몇몇 요소가 제대로 보이도록 JScript를 사용하고 있습니다. 하지만 여러분의 브라우저 설정에서 스크립트 기능이 꺼져있으므로, 현재 페이지를 제대로 확인하시려면 스크립트 기능을 켜주셔야 합니다. React - Hooks - useCallback 훅
React – Hooks – useCallback 훅
4개월전 작성
4개월전 수정

React

useCallback

React ‘Use Callback’ 훅은 메모된 콜백 기능을 반환한다.

⭐ 메모를 다시 계산할 필요가 없도록 값을 캐싱하는 것으로 생각한다.

이를 통해 리소스 집약적인 기능을 분리하여 모든 렌더에서 자동으로 실행되지 않도록 할 수 있다.

useCallback 훅은 종속성 중 하나가 업데이트될 때만 실행된다.

성능을 향상시킬 수 있다.

⭐ useCallback과 useMemo 훅은 유사하다. 주요 차이점은 useMemo는 메모된 값을 반환하고 useCallback은 메모된 기능을 반환한다는 것이다.

문제

useCallback을 사용하는 한 가지 이유는 구성 요소가 변경되지 않는 한 구성 요소가 다시 렌더링되는 것을 방지하기 위함이다.

이 예에서는 Todos 구성 요소가 변경되지 않는 한 Todos 구성 요소가 다시 렌더링되지 않는다고 생각할 수 있다.

예제 – index.js
import { useState } from "react";
import ReactDOM from "react-dom/client";
import Todos from "./Todos";

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

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

  return (
    <>
      <Todos todos={todos} addTodo={addTodo} />
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </>
  );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
예제 – Todos.js
import { memo } from "react";

const Todos = ({ todos, addTodo }) => {
  console.log("child render");
  return (
    <>
      <h2>My Todos</h2>
      {todos.map((todo, index) => {
        return <p key={index}>{todo}</p>;
      })}
      <button onClick={addTodo}>Add Todo</button>
    </>
  );
};

export default memo(Todos);
기본 예시
예제 보기

 

이것을 실행해 보고 count increment 버튼을 클릭한다.

Todos 구성 요소는 Todos가 변경되지 않더라도 다시 렌더링된다는 것을 알 수 있다.

왜 이렇게 안 되나? 우리는 메모를 사용하고 있기 때문에 카운트가 증가하면 Todos 상태나 addTodo 기능이 변경되지 않기 때문에 Todos 구성 요소가 다시 렌더링되어서는 안 된다.

이것은 “참조 평등”이라고 불리는 것 때문이다.

구성 요소가 다시 렌더링될 때마다 그 기능이 다시 생성된다.
이 때문에 실제로 addTodo 기능이 변경되었다.

해결책

이를 해결하기 위해 필요하지 않은 경우 ‘useCallback’ 훅을 사용하여 기능이 재생되지 않도록 할 수 있다.

‘useCallback’ 훅을 사용하여 ‘Todos’ 구성 요소가 불필요하게 재렌더링되는 것을 방지한다.

예제 – index.js
import { useState, useCallback } from "react";
import ReactDOM from "react-dom/client";
import Todos from "./Todos";

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

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

  return (
    <>
      <Todos todos={todos} addTodo={addTodo} />
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </>
  );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
예제 – Todos.js
import { memo } from "react";

const Todos = ({ todos, addTodo }) => {
  console.log("child render");
  return (
    <>
      <h2>My Todos</h2>
      {todos.map((todo, index) => {
        return <p key={index}>{todo}</p>;
      })}
      <button onClick={addTodo}>Add Todo</button>
    </>
  );
};

export default memo(Todos);
기본 예시
예제 보기

 

이제 Todos 구성 요소는 Todos prop가 변경될 때만 다시 렌더링된다.

참고
Mingg`s Diary
밍구
공부 목적 블로그