[ React ] useCallback 톺아보기

·2024년 3월 18일

useCallback

useCallback 훅은 인수로 넘겨받은 콜백 함수 자체를 기억하여, 특정 함수를 재사용할 수 있다.
useCallback의 첫 번째 인수는 함수를, 두번째 인수로는 의존성 배열을 집어 넣을 수 있다.
useCallback을 사용하지 않는다면, 컴포넌트가 렌더링될 때마다
모든 내부 변수가 초기화되어 함수가 변수에 다시 할당되지만,
useCallback을 사용한다면, 컴포넌트가 렌더링 되더라도
함수가 초기화되는 것을 막을 수 있다.

const ChildComponent = memo(({name, value, onChange}) => {
  useEffect(() => {
    console.log('render', name)
  })
  
  return (
    <>
     <h1>
      {name} {value ? '켜짐' : '꺼짐'}
     </h1>
     <button onClick={onChange}>toggle</button>
</>
)
})

function App() {
  const [status1, setStatus1 ] = useState(false)
  const [status2, setStatus2 ] = useState(false)
  
  const toggle1 = () => {
    setStatus1(!status1)
}
  const toggle2 = () => {
    setStatus2(!status2)
}
    return (
      <>
      <ChildComponent name="1" value={status1} onChange={toggle1}/>
      <ChildComponent name="2" value={status2} onChange={toggle2}/>   
     </>
)
}

해당 예시는 ChildComponent에 memo를 사용해 name, value, onChange 값을 모두 기억하고 이 값이 변경되지 않았을 때에는 렌더링되지 않도록 작성한 코드이다.
하지만, 어느 한 버튼을 클릭하면,
클릭된 컴포넌트 외에도 클릭하지 않은 컴포넌트도 렌더링이 되는데
그 이유는 state 값이 바뀌면서 APP 컴포넌트가 리렌더링되고,
그때마다 매번 onChange로 넘기는 함수가 재생성되고 있기 때문이다.

useCallback을 추가해보자

const ChildComponent = memo(({name, value, onChange}) => {
  useEffect(() => {
    console.log('render', name)
  })
  
  return (
    <>
     <h1>
      {name} {value ? '켜짐' : '꺼짐'}
     </h1>
     <button onClick={onChange}>toggle</button>
</>
)
})

function App() {
  const [status1, setStatus1 ] = useState(false)
  const [status2, setStatus2 ] = useState(false)
  
  const toggle1 = useCallback(
   function toggle1() {
    setStatus1(!status1)
  },
    [status1],
  )
  
  const toggle2 = useCallback(
   function toggle2() {
    setStatus2(!status2)
  },
    [status2],
  )
    return (
      <>
      <ChildComponent name="1" value={status1} onChange={toggle1}/>
      <ChildComponent name="2" value={status2} onChange={toggle2}/>   
     </>
)
}

위의 예시를 실행하면, 해당 의존성이 변경되었을 때에만 함수가 재생성되는 것을 알 수 있다.

profile
new blog: https://hae0-02ni.tistory.com/

0개의 댓글