useCallback

alajillo·2021년 10월 8일
0

React

목록 보기
8/12
post-thumbnail

useCallback

useCallback은 콜백 함수를 기억해야 할때 쓰입니다.

import {useCallback, useState} from 'react'
import ChildComponent from './ChildComponent'
import DummyComponent from './DummyComponent'
function App{
console.log("App render!!")
	const [value, setValue] = useState(0)
	const changeValue = (newValue)=>{setValue(newValue)}
	const dummyCallback = () => {console.log(' ')}
	return { 
		<div>
			<ChildComponent callback={changeValue} prop={value}/>
			<DummyComponent callback={dummyCallback}/>
		</div>
	}
}

위에 코드를 간단하게 보면 App컴포넌트는 ChildComponent와 DummyComponent를 자식 컴포넌트로 가지고 있고 ChildComponent에게는 콜백함수 와 state를 전달해주고 DummyComponent에게는 콜백함수를 전달해주고 있다.

여기서 컴포넌트가 다시 렌더링 되는 조건 3가지를 보면

  1. 상태가 변경됬을때
  2. 부모컴포넌트의 상태가 변경되었을때
  3. 부모컴포넌트로 부터 전달받은 props가 변경되었을때

여기서 2번은 React.memo를 이용해서 부모컴포넌트의 상태가 변했을때 자식컴포넌트의 상태 혹은 전달받은 props가 변경되지 않는 이상 방지 할수 있다.

그래서 코드로는 안보이지만 DummyComponent 와 ChildComponent에게 React.memo를 이용해서 부모 컴포넌트의 상태가 변경되더라도 다시 렌더링 되지 않게 조치를 해주었다고 가정한다.

여기서 ChildComponent 내부에서 changeValue 콜백함수를 이용해서 value를 변경했을때는 어떤 컴포넌트들이 변경될까?

상태변경에 따른 렌더링 데이터의 흐름

예상

  1. ChildComponent에서 changeValue를 통해서 App컴포넌트의 상태 value가 변경된다.
  2. APP컴포넌트의 상태가 변경되었기 때문에 App컴포넌트가 다시 렌더링 된다.
  3. ChildComponent가 App컴포넌트에게 받은 props value가 변경되었기 때문에 ChildComponent또한 다시 렌더링 된다.

이런 결과를 예상 했지만 아니다.

실제

  1. ChildComponent에서 changeValue를 통해서 App컴포넌트의 상태 value가 변경된다.
  2. APP컴포넌트의 상태가 변경되었기 때문에 App컴포넌트가 다시 렌더링 된다.
  3. ChildComponent가 App컴포넌트에게 받은 props value가 변경되었기 때문에 ChildComponent또한 다시 렌더링 된다.
  4. App컴포넌트에서 다시 dummyCallback을 선언 하면서 새로운 메모리 주소 값이 할당 된다.
  5. App컴포넌트에게서 받았던 dummyCallback(정확히는 할당된 메모리 주소값)이 변경되었기 때문에 DummyComponent또한 변경된다.

억울한 DummyComponent

DummyComponent 입장에서는 매우 억울한 상황이다. 나도 안변하고 나한테 들어오는 props들도 안변하고 부모컴포넌트가 다시 렌더링 되도 다시 렌더링 되는 것을 방지하기 위해 사용했던 React.memo도 무용지물이 되었다.

이런 억울한 DummyComponent를 위해서 나온 것이 useCallback이다.

useCallback의 사용법

const callbackFunction = useCallback(함수,배열)

useEffect와 사용법이 매우 유사하다. 2개의 인자를 받고 첫번째는 실행될 콜백함수, 두번째는 배열이다.

useEffect는 두번째의 받은 배열안에 값들이 변경되었을때 첫번째 함수를 작동하는 방식이고

useCallback은 마찬가지로 배열안에 값들이 변경되었을때만 변경된다.

말이 조금 이상하니까 useCallback의 배열은 빈배열을 넣으면 useCallback이 재 선언되는 과정에서 메모리 주소값이 변경되어 렌더링 되는 것을 막아주는 용도로만 일단 쓰기로 해야겠다.

profile
Developer's High

0개의 댓글