728x90

useEffect와 useCallback

들어가며

  • 리액트에서 사용되는 @useCallback@과 @useEffect@에 대해 알아보자.

 

@useCallback@

  • 리액트에서 함수를 메모이제이션(Memoization)하는 데 사용된다.
  • 불필요한 함수의 재생성을 방지하고, 함수가 의존하는 값이 변경될 때만 새로운 함수를 생성하도록 할 수 있다.

 

예제 코드
  • 아래의 코드에서 @handleClick@ 함수는 @count@ 변수가 변경될 때만 재생성 된다.
  • 그렇지 않을 경우 @handleClick@ 함수는 재생성되지 않으며, 같은 함수를 계속 사용하게 된다.
  • 이렇게 할 경우 함수의 재생성을 최소화하여 성능 최적화를 하는데 도움을 줄 수 있다.
import React, { useCallback, useState } from 'react';

const MyComponent = () => {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log('Button clicked!', count);
  }, [count]);     // count가 변경될 때만 handleClick이 재생성된다.

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Click me</button>
      <button onClick={() => setCount(count + 1)}>Increase Count</button>
    </div>
  );
};

export default MyComponent;

 

@useEffect@

  • 함수형 컴포넌트에서 사이드 이펙트(Side Effect)를 수행하는 데 사용된다.
    • 사이드 이펙트란 데이터 가져오기, 수동으로 DOM 수정하기, 구독 설정 및 해제 등의 작업을 말한다.

 

예제 코드
import React, { useEffect, useState } from 'react';

const MyComponent = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    // 컴포넌트가 마운트될 때 작업 수행
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));

    // 컴포넌트 언마운트 시 클린업 작업 수행
    return () => {
      console.log('컴포넌트가 언마운트되었습니다.');
    };
  }, []); 

  return (
    <div>
      {data ? <p>Data: {JSON.stringify(data)}</p> : <p>Loading...</p>}
    </div>
  );
};

export default MyComponent;

 

참고

  • 다음과 같이 @useEffect@ 훅의 의존성 배열에 함수(Function)을 넣고자 할 경우, 해당 함수를 @useCallback@ 훅으로 감싸준다.
    • 그렇지 않을 경우, 컴포넌트가 랜더링될 때마다 의존성 배열에 넣은 함수가 재생성되어 무한 루프에 빠질 수 있다.
App.jsx
// useCallback을 사용할 경우, 함수가 컴포넌트가 리랜더링될 때마다 재생성되지 않는다.
const handleRemovePlace = useCallback(function handleRemovePlace() {
    setPickedPlaces((prevPickedPlaces) =>
      prevPickedPlaces.filter((place) => place.id !== selectedPlace.current)
    );
    setModalIsOpen(false);

    // 로컬 스토리지 기능 사용
    const storedIds = JSON.parse(localStorage.getItem("selectedPlaces")) || [];
    localStorage.setItem(
      "selectedPlaces",
      JSON.stringify(storedIds.filter((id) => id !== selectedPlace.current))
    );
}, []);

return (
    <>
      <Modal open={modalIsOpen} onClose={handleStopRemovePlace}>
        <DeleteConfirmation
          onCancel={handleStopRemovePlace}
          onConfirm={handleRemovePlace}
        />
      </Modal>
    </>
);

 

DeleteConfirmation.jsx
export default function DeleteConfirmation({ onConfirm, onCancel }) {
  useEffect(() => {
    console.log("TIMER SET");
    const timer = setTimeout(() => {
      onConfirm();
    }, 3000);

    // Clean Up
    return () => {
      console.log("Cleaning up timer");
      clearTimeout(timer);
    };
  }, [onConfirm]);
 
  // ...
}

 

참고 사이트

 

useEffect – React

The library for web and native user interfaces

react.dev

 

useCallback – React

The library for web and native user interfaces

ko.react.dev

 

728x90