본문 바로가기
Q&A해결2024년 6월 11일1분 읽기

React useEffect 무한 루프 원인이 뭔가요

프
프론트수진
조회 898댓글 2

React 컴포넌트에서 useEffect를 사용하는데 무한 렌더링이 발생합니다.

const [data, setData] = useState([]);
const [filter, setFilter] = useState({});

useEffect(() => {
  fetchData(filter).then(res => setData(res));
}, [filter]);

// 다른 곳에서
const handleClick = () => {
  setFilter({ category: 'all' });  // 매번 새 객체 생성
};

filter가 바뀔 때만 fetch하고 싶은데, 컴포넌트가 계속 리렌더링됩니다. 콘솔에 네트워크 요청이 끝없이 찍히고 있어요. 의존성 배열에 filter를 넣어야 하는 것 같은데, 어떻게 해야 무한 루프를 막을 수 있을까요?

댓글 2

김김영삼2년 전

전형적인 useEffect 무한 루프 패턴입니다! 원인은 객체의 참조 비교에 있어요.


JavaScript에서 { category: 'all' } !== { category: 'all' }입니다. 매 렌더링마다 새 객체가 생성되니 useEffect가 계속 실행됩니다.


해결 방법 1: useMemo 사용


const filter = useMemo(() => ({ category: 'all' }), [category]);

해결 방법 2: 원시값으로 분리


const [category, setCategory] = useState('all');

useEffect(() => {
fetchData({ category }).then(res => setData(res));
}, [category]); // 문자열이므로 정확한 비교 가능

해결 방법 3: JSON.stringify 비교 (임시방편)


const filterStr = JSON.stringify(filter);
useEffect(() => {
fetchData(JSON.parse(filterStr)).then(res => setData(res));
}, [filterStr]);

방법 2가 가장 깔끔하고 권장됩니다. 가능하면 의존성 배열에는 원시값(string, number, boolean)만 넣으세요.

프프론트수진김영삼2년 전

아! 객체 참조 비교 문제였군요. 방법 2로 수정하니까 바로 해결됐습니다. 상세한 답변 감사합니다! 🎉

Ctrl+Enter로 등록