프로그래밍 언어/React

[React Hooks]useCallback

claire 2022. 7. 12. 11:19

useCallback 또한 메모이제이션 기법으로 컴포넌트 성능을 최적화 시켜준다. 

메모이제이션은 자주 사용되는 값을 받아오기 위해 반복적으로 계산을 해야한다면 이전에 계산한 값을 캐싱해둠으로 해당 값이 필요할 때마다 반복적으로 계산하는 것이 아니라 메모리에서 꺼내서 재사용하는 최적화 기법이다. 

useMemo의 인자로 콜백함수를 넣어주면 이 함수가 리턴하는 값을 메모이제이션 해주는 것이다. 

useCallback은 인자로 전달한 콜백함수 자체를 메모이제이션 해준다. 이 함수가 필요할 때마다 메모리에서 가져와서 재사용한다. 

JS에서 함수는 객체의 한 종류이다. 

calculate라는 변수에 객체가 할당되는 것이다. 

리액트에서 함수형 컴포넌트는 함수이다. 그래서 렌더링된다는 것은 component 함수가 호출된다는 것이고, 함수 내부의 모든 변수가 초기화 된다는 것이다. 

컴포넌트가 리렌더링이 되더라도 컴포넌트가 초기화되는 것을 막을 수 있다. 즉, 컴포넌트가 처음 렌더링 될 때만 이 함수 객체를 만들어서 calculate를 초기화해주고 이후에 렌더링될 때는 calculate 변수가 새로운 함수 객체를 다시 할당받는 게 아니라 이미 할당받은 함수 객체를 가지고 있으면서 재사용할 수 있게 되는 것이다. 

- useCallback 구조

첫번째 인자는 메모이제이션해줄 콜백함수, 두번째 인자는 의존성 배열

의존성 배열 내부에 있는 값이 변경되지 않는 이상 초기화되지 않는다. 만약 의존성 배열 내부에 명시해준 값이 변경되면 그제서야 새로 만들어진 함수 객체로 초기화된다. 

 

- useCallback 사용법

import { useCallback } from "react";
import { useEffect } from "react";
import { useState } from "react";

function App() {
  const [number, setNumber] = useState(0);
  const [toggle, setToggle] = useState(true);
  
  //someFunction에 함수 객체가 할당되는데 이 객체는 다른 메모리 공간에 저장되고 이 주소가
  //변수에 들어간다. 따라서 리렌더링시 이전과는 다른 메모리 주소가 들어간다. 따라서 useEffect가 계속 불림.
  // const someFunction = () => {
  //   console.log(`someFunc:number:${number}`);
  //   return;
  // };

  const someFunction = useCallback(() => {
    console.log(`someFunc:number:${number}`);
    return;
  }, [number]);

  useEffect(() => {
    console.log("someFunction 변경");
  }, [someFunction]);

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(e.target.value)}
      />
      <button onClick={() => setToggle(!toggle)}>{toggle.toString()}</button>
      <br />
      <button onClick={someFunction}>Call someFunc</button>
    </div>
  );
}

export default App;

(2)

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

function App() {
  const [size, setSize] = useState(100);
  const [isDark, setIsDark] = useState(false);

  const createBoxStyle = useCallback(() => {
    return {
      backgroundColor: "pink",
      width: `${size}px`,
      height: `${size}px`,
    };
  }, [size]);
  return (
    <div style={{ background: isDark ? "black" : "white" }}>
      <input
        type="number"
        value={size}
        onChange={(e) => setSize(e.target.value)}
      />
      <button onClick={() => setIsDark(!isDark)}>Change Theme</button>
      <Box createBoxStyle={createBoxStyle} />
    </div>
  );
}

export default App;

- box.js

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

const Box = ({ createBoxStyle }) => {
  const [style, setStyle] = useState({});

  useEffect(() => {
    console.log("박스 키우기👀");
    setStyle(createBoxStyle());
  }, [createBoxStyle]);

  return <div style={style}></div>;
};

export default Box;

 

출처 : 유튜브 별코딩  https://www.youtube.com/watch?v=XfUF9qLa3mU 

별코딩은 정말 강추입니다!! 설명 정말 잘해주십니다!! 초심자에게 큰 도움이 됩니다.