프론트엔드/React

[React] useCallback()

진기명기 2023. 6. 15. 17:18
팀 프로젝트를 진행하면서 '찜하기' 기능을 구현하는 도중에 백엔드 서버로 불필요한 호출이 반복되는 것을 발견하였다.
어떻게 해야 불필요한 호출을 막을 수 있을까 고민하던 중에 팀원 한 분이 useCallback에 대해서 말씀해 주셔서 찾아보았다 🙌🏻

 

 

 


💡 useCallback이란?
👉🏻 react 라이브러리에서 제공하는 훅(Hook)에 해당
👉🏻 함수를 메모이제이션하여 동일한 콜백 함수 인스턴스를 재사용
      ✅ 의존성 배열의 값이 변경되지 않는 한, 같은 콜백 함수 인스턴스를 계속해서 사용 가능
👉🏻 아래와 같은 불필요한 함수 생성을 방지 
      👻 React 컴포넌트가 렌더링 될 때마다 함수들이 새로 생성 ➡️ 해당 함수를 사용하는 다른 컴포넌트도 함께 리렌더링 
      👻 부모 컴포넌트가 업데이트 되거나 상태값이 변경될 때 자식 컴포넌트가 다시 렌더링 되는 경우 

 

 

 

📝 예시
const memoizedCallback = useCallback(callback, dependencies)
✅ callback : 메모이제이션할 콜백 함수
✅ dependencies : 의존성 배열로, 배열 안의 값들이 변경될 때마다 콜백 함수를 새로 생성

💡 즉, dependencies 배열의 값이 변경되면, callback 함수가 새로 생성되고, 그렇지 않은 경우에는 메모이제이션 된 콜백 함수를 재사용

 

 

 

💁‍♀️ '찜하기' 기능에 useCallback 사용하기
const handleOnCancel = useCallback(async () => {
  if (newIsSaved !== isSaved) {
    try {
      const response = await fetch(api, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: token,
        },
      })

      if (!response.ok) {
        throw new Error("찜하기를 처리하는데 실패했습니다.")
      }

      setIsSaved(newIsSaved)
      
    } catch (error) {
      console.error(error)
      setNewIsSaved(isSaved)
    }
  }
  
  onClose()
  
}, [의존성 배열])
✅ handleSaveClick ➡️ 찜하기 버튼을 누를 때마다 newIsSaved 상태를 토글
✅ handleOnCancel ➡️ useCallback을 사용하여 메모이제이션 ➡️ 모달창이 닫힐 때 호출되는 콜백 함수
✅ useCallback의 의존성 배열 [ ] 전달 ➡️ 배열에 포함된 값들의 변경에만 반응

💡 따라서 handleSaveClick 함수를 통해 찜하기 버튼을 눌렀을 때, newIsSaved 상태를 토글 하고,
handleOnCancel 함수로 모달창이 닫힐 때만 API 요청을 보내어 불필요한 함수 생성을 방지 ☺️