[React] usecallback

정호·2024년 7월 30일
0

TIL

목록 보기
19/19

useEffect 사용시 문제점

Effect함수에 속성이나 상태값을 사용한다면 dependency로 추가해야한다. 이 코드에서 onConfirm속성을 의존성으로 추가하려하는데 onConfirm은 함수

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

    return () => {
      console.log("Cleaning up timer");
      clearTimeout(timer);
    };
  }, [onConfirm]);
  • 종속성으로서 함수를 추가할 때는 무한 루프를 생성할 위험이 있음

open과 같은 의존성을이 배열에 추가할 때, 이 Modal 컴포넌트에서 리액트가 이 Effect 함수를 다시 실행해야 하기 때문

function Modal({ open, children, onClose }) {
  const dialog = useRef();

  useEffect(() => {
    if (open) {
      dialog.current.showModal();
    } else {
      dialog.current.close();
    }
  }, [open]);

onConfirm 함수

//App.jsx
  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))
    );
  }

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

js에서 함수는 객체이므로 이 handleRomovePlace 함수 객체로 앱 컴포넌트 함수가 실행될 때마다 재생성

  • 리액트는 새로운 값, 새로운 함수를 보고
    이전의 값 또는 함수와 비교하게 되고
    그리고는 이 둘이 다르다고 판단을 내린다.

그 이유는 앱 컴포넌트가 다시 렌더링될 때 함수가 다시 실행되면 완전히 새로운 handleRemovePlace 함수가 생성
이 함수를 DeleteConfirmation에서 받은 후에는 리액트는 이 새로운 값, 새로운 함수를 보고 이전의 값 또는 함수와 비교하게되고 둘이 다르다고 판단
무한루프 발생 위험


usecallback

React에 함수가 항상 재생성되지 않도록 하기 위해 사용할 수 있는 hook이 제공 함수를 안에 넣어주기만 하면됨(첫번째인자) , 종속성(두번째인자)

  • 둘러싼 함수를 return, 안쪽에 함수가 재생성되지 않고 내부에 메모리로서 저장
  • 두번째인자:함수 안에 사용되는 prop또는 state value값 추가 (useEffect 유사)
  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))
    );
  }, []);
profile
열심히 기록할 예정🙃

0개의 댓글