함수는 객체(object)다.
그동안 강의를 들으며 이 문장을 접했을 때는 '아 그렇구나(이해 못함)' 하고 넘겼었다.
이번 챌린지 예제를 통해 완전히 이해할 수 있었다.
아래 코드는 무한 루프에 걸리는 코드다. useEffect 훅에 dependency로 getDetailedPage가 있다. 즉, getDetailedPage에 변화가 있을 때마다 useEffect 훅을 실행한다.
getDetailedPage 함수를 보자. Detail 컴포넌트가 렌더될 때, 이 함수는 객체로써 새로운 메모리 공간을 할당 받는다(참조 한다). 1번 메모리에 할당되었다고 가정하자.
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
const Detail = () => {
const [ data, setData ] = useState(null);
const { id } = useParams();
const getDetailedPage = async () => {
const json = await (await fetch(`https://marvel-proxy.nomadcoders.workers.dev/v1/public/characters/${id}`)
.json();
setData(json);
)};
useEffect(() => {
getDetailedPage();
}, [getDetailedPage]);
return <h1>Hello</h1>;
};
export default Detail;
아래 코드는 useCallback을 사용해서 getDetailedPage를 기억하게 만들었다. 컴포넌트가 재렌더되어도 id 값만 바뀌지 않는다면 새로운 메모리에 할당되지 않는다. 즉, getDetailedPage가 바뀌지 않는다.
import { useEffect, useCallback, useState } from "react";
import { useParams } from "react-router-dom";
const Detail = () => {
const { id } = useParams();
const [ data, setData ] = useState(null);
const getDetailedPage = useCallback(async () => {
const json = await (await fetch(`https://marvel-proxy.nomadcoders.workers.dev/v1/public/characters/${id}`)
.json();
setData(json);
)}, [id]);
useEffect(() => {
getDetailedPage();
}, [getDetailedPage]);
return <h1>Hello</h1>;
};
export default Detail;
함수는 객체이기 때문에 컴포넌트가 실행될 때마다 새로운 메모리에 할당된다.
이는 자칫하면 무한 루프를 만들어낼 수 있으므로 useCallback을 사용해주는 게 좋다.