[에러 해결] React Hook useEffect has missing dependencies: ... Either include them or remove the dependency array react-hooks/exhaustive-deps

지은·2023년 4월 17일
3

에러 해결

목록 보기
3/7

에러 로그 1

Github Actions로 배포 자동화를 하는 도중 아래의 eslint 오류가 엄청 많이 떴다.

React Hook useEffect has missing dependencies: 'deleteItemFromCart', 'item' 
Either include them or remove the dependency array  react-hooks/exhaustive-deps

에러가 발생한 곳

useEffect(() => {
	item.quantity = quantityInput; // 상품의 개수나
	item.price = milesTicketInput; // 마일티켓 개수가 변경되면 업데이트 해준다.

	if (item.quantity === 0) { // 개수가 0개가 될 경우에는 카트에서 삭제한다.
		deleteItemFromCart();
	}
}, [quantityInput, milesTicketInput]); // 개수와 마일티켓 input의 값이 변경될 때마다 useEffect 실행

찾아보니 이 경고는 useEffect 안에서 useEffect의 의존성 배열에 정의되지 않은 변수를 사용하기 때문에 발생하는 것이다.
즉, useEffect 안에서 deleteItemFromCartitem이라는 변수를 사용하는데, 의존성 배열에 위의 두 변수가 추가되어있지 않다는 것이다.

따라서 해당 경고를 해결하기 위해서는 useEffect 함수의 의존성 배열에 deleteItemFromCartitem을 추가하거나, 해당 변수를 사용하지 않는 방법 중 하나를 선택해야 한다.

해결 방법 1

deleteItemFromCartitem을 useEffect의 의존성 배열에 추가한다.

useEffect(() => {
	item.quantity = quantityInput;
	item.price = milesTicketInput;

	if (item.quantity === 0) {
		deleteItemFromCart();
	}
}, [quantityInput, milesTicketInput, item, deleteItemFromCart]);

해결 방법 2

deleteFromCart 함수를 useEffect 안으로 옮겨준다. 이렇게 하면 deleteFromCart를 의존성 배열에 추가할 필요가 없다.

useEffect(() => {
	const deleteItemFromCart = () => {
		setCart(cart.filter((cartItem) => cartItem.UniqueEntryID !== item.UniqueEntryID));
	}
  // ...
}, [quantityInput, milesTicketInput, item]);

해결 방법 3

혹은 eslint-disable-next-line react-hooks/exhaustive-deps 주석을 추가하면 해당 코드 라인에서만 의존성 배열 경고를 무시할 수 있다. 위와 같이 다만, 이 방법은 의존성 배열이 불완전한 상태로 남아있을 수 있으므로 주의해서 사용해야 한다.

useEffect(() => {
  // 생략...
  // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

에러 로그 2

나는 1번 방법으로 해결하는 것으로 선택했다. 1번처럼 코드를 수정하고 다시 빌드를 했더니 또 다른 경고가 발생했다.

Line 14:8:  The 'deleteItemFromCart' function makes the dependencies of useEffect Hook (at line 25) change on every render. 
To fix this, wrap the definition of 'deleteItemFromCart' in its own useCallback() Hook  react-hooks/exhaustive-deps

해석하면 useEffect의 의존성 배열에 있는 deleteItemFromCart 함수가 매 렌더링마다 useEffect의 종속성을 변화시킨다는 것이다.

deleteItemFromCart 함수는 변하지 않는데 왜 종속성을 변화시키지? 라고 생각할 수 있다.

하지만 JavaScript는 참조 동등성(referential equality)을 기반으로 작동하기 때문에, 객체(함수 또한 객체)는 메모리에서 동일한 객체를 참조하는 경우에만 서로 동일하다고 여긴다.

그래서 JavaScript는 매 렌더링마다 새롭게 생성되는 deleteItemFromCart 함수가 항상 다르다고 받아들여 useEffect를 실행하는 것이다.

이를 해결하려면 해당 함수를 useCallback으로 감싸면 된다.

수정 전

const deleteItemFromCart = () => {
	setCart(cart.filter((cartItem) => cartItem.UniqueEntryID !== item.UniqueEntryID));
};

수정 후

const deleteItemFromCart = useCallback(() => {
	setCart(cart.filter((cartItem) => cartItem.UniqueEntryID !== item.UniqueEntryID));
}, [cart, item.UniqueEntryID, setCart]);

이때, useCallback의 의존성 배열 안에 해당 함수에서 사용하는 변수들을 넣어줘야 한다.
넣어주지 않으면 어떻게 되냐고? (나도 알고 싶지 않았다..)
아래와 같이 의존성 오류가 또 발생할 수 있으니, useCallback에서 사용하는 변수와 함수들을 의존성 배열에 넣어줘야 한다.

Line 16:5:  React Hook useCallback has missing dependencies: 'cart', 'item.UniqueEntryID', and 'setCart'.
Either include them or remove the dependency array. If 'setCart' changes too often, 
find the parent component that defines it and wrap that definition in useCallback  react-hooks/exhaustive-deps

Fix the "Function makes the dependencies of useEffect Hook change on every render" warning in React

profile
블로그 이전 -> https://janechun.tistory.com

4개의 댓글

comment-user-thumbnail
2023년 4월 17일

저도 무한 렌더링 걸렸을 때 지은님이랑 다른 방법으로 해결했는데, useCallback으로 해결 잘하신거같네요 대단합니다

답글 달기
comment-user-thumbnail
2023년 4월 22일

함수는 같은 기능을 함수를 새로 만들어 실행한다... 개념 리마인드 하구 갑니다...!

답글 달기
comment-user-thumbnail
2023년 4월 23일

해결 방법 여러개 적어주셔서 잘 기억하고 가겠습니당 ㅎㅎ

답글 달기
comment-user-thumbnail
2023년 4월 23일

에러 해결법 잘봤습니다! 많이 보이는 에러죠 !

답글 달기