즐코

useCallback (for 컴포넌트 최적화 / useMemo의 함수버전) 본문

React

useCallback (for 컴포넌트 최적화 / useMemo의 함수버전)

YJLEE_KR 2022. 5. 12. 22:41

useMemo 와 용도는 동일하다.  https://yjleekr.tistory.com/68 

다른 점은 useMemo는 내부의 콜백함수가 리턴하는 값을 메모이제이션 주는 반면,

useCallback은 콜백함수 자체를 메모이제이션 해준다. 

 

아래 예시처럼, 함수 자체를 메모이제이션 해두고, 함수가 필요할때마다 새로 생성하는 게 아니라, 메모리에 저장해두고 필요할때마다 재사용할 수 있게 도와준다. 따라서, 함수형 컴포넌트 내에서 다른 값이 변경되어 컴포넌트가 재렌더링되어도 저 useCallback 으로 감싸고 있는 함수는 다시 생성되지 않고, 이전에 메모이제이션해둔 함수를 가져와서 쓰는 거다.

 

다만, 두번째 인자로 들어가는 의존성 배열의 값이 변경될때만 함수가 재선언된다. 

 

const calculate = useCallback((num)=>{
	return num+1
},[item])

 

예시> 

아래 App은 상태를 2개 가지고 있다. 하나는 박스 사이즈에 관련된 것, 또 다른 하나는 다크모드에 관련된 것이다.

이 때 , input에 숫자를 넣고 박스사이즈를 바꿔주면 그거에 맞춰서 박스가 커지고 작아진다. 그러면 createBoxStyle 함수가 바뀌고 당연히 Box 컴포넌트 안에 있는 useEffect가 발동되어서 '박스사이즈 조정'이라는 콘솔이 찍힐것이다. 

 

근데, 여기서 다크모드로 바꿔주는 버튼을 누르면 isDark라는 상태가 바뀌었기 때문에 컴포넌트가 새로 렌더링되고,

만약 createBoxStyle이 아래 코드와 달리 useCallback으로 감싸져있지 않다면,, 내부의 createBoxStyle 함수도 새로 생성된다. 왜냐하면 함수도 객체이므로, 렌더됨과 동시에 참조값이 새로 반영되고 리액트는 이 createBoxStyle이 같은 함수여도 다른 함수라고 여기고 Box내부의 useEffect 콜백함수가 실행되어 '박스사이즈 조정'이 콘솔창에 찍히게 된다..

 

그래서 createBoxStyle 함수를 useCallback으로 감싸주고 사이즈가 바뀔때만 재선언되게끔 했더니 다크모드 버튼을 눌러도 useEffect가 발동되지 않는다. 

 

// App.js

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

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

  const createBoxStyle = useCallback(() => {
    return {
      backgroundColor: 'yellow',
      width: `${size}px`,
      height: `${size}px`
    };
  }, [size])


  return (
    <div style={{
      backgroundColor: isDark ? 'black' : 'white',
    }}>
      <input type="number" value={size} onChange={(e) => setSize(e.target.value)} />
      <button onClick={() => setIsDark(!isDark)}>change background</button>
      <Box createBoxStyle={createBoxStyle} />
    </div>
  )
}

export default App;

 

// Box.jsx

import { useEffect, 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&list=PLZ5oZ2KmQEYjwhSxjB_74PoU6pmFzgVMO&index=7

'React' 카테고리의 다른 글

useMemo (for 컴포넌트 최적화)  (0) 2022.05.12
Context API 복습  (0) 2022.05.11
useRef 복습 - 변수관리 (state와는 다르다!)  (0) 2022.05.11
useEffect 복습  (0) 2022.05.10
redux-middleware (redux-thunk)  (0) 2022.05.04
Comments