TypeScript

React useEffect 의존성 경고

코샵 2025. 2. 14. 10:13
반응형
더보기

React Hook useEffect has a missing dependency: ''. Either include it or remove the dependency array

React의 useEffect Hook을 사용할 때 자주 마주치는 경고 메시지에 대해 알아보고, 이를 올바르게 해결하는 방법을 살펴보겠습니다.

경고가 발생하는 일반적인 상황

const [data, setData] = useState([]);
const fetchData = async () => {
    const response = await api.getData();
    setData(response.data);
};

// 경고 발생: fetchData가 의존성 배열에 없음
useEffect(() => {
    fetchData();
}, []);

문제의 원인

  1. useEffect 내부에서 사용되는 외부 변수나 함수가 의존성 배열에 포함되지 않은 경우
  2. 컴포넌트가 리렌더링될 때마다 함수가 새로 생성되어 무한 루프가 발생할 수 있는 상황

해결방법

의존성 추가하기

const [data, setData] = useState([]);
const fetchData = async () => {
    const response = await api.getData();
    setData(response.data);
};

// fetchData를 의존성 배열에 추가
useEffect(() => {
    fetchData();
}, [fetchData]); // 하지만 이 방법은 무한 루프를 발생시킬 수 있음

 

useCallback 사용하기

const [data, setData] = useState([]);
const fetchData = useCallback(async () => {
    const response = await api.getData();
    setData(response.data);
}, []); // 함수를 메모이제이션

useEffect(() => {
    fetchData();
}, [fetchData]); // 이제 안전하게 의존성 추가 가능

 

useEffect 내부로 함수 이동

const [data, setData] = useState([]);

useEffect(() => {
    const fetchData = async () => {
        const response = await api.getData();
        setData(response.data);
    };

    fetchData();
}, []); // 외부 의존성이 없으므로 빈 배열 사용 가능

 

props를 사용하는 경우

interface Props {
    userId: string;
    onDataLoad: (data: any) => void;
}

const DataFetcher: React.FC<Props> = ({ userId, onDataLoad }) => {
    useEffect(() => {
        const fetchData = async () => {
            const response = await api.getUserData(userId);
            onDataLoad(response.data);
        };

        fetchData();
    }, [userId, onDataLoad]); // props를 의존성 배열에 포함

    return <div>Loading...</div>;
};

 

상태 업데이트 함수 처리

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

// 올바른 방법
useEffect(() => {
    // setState 함수는 의존성 배열에 포함할 필요 없음
    const timer = setInterval(() => {
        setCount(prev => prev + 1);
    }, 1000);

    return () => clearInterval(timer);
}, []); // 빈 배열 사용 가능

 

객체나 배열을 다룰 때

const [filters, setFilters] = useState({ category: 'all' });

// 잘못된 방법
useEffect(() => {
    fetchData(filters);
}, [filters]); // 객체라서 매 렌더링마다 새로 생성됨

// 올바른 방법
useEffect(() => {
    fetchData(filters.category);
}, [filters.category]); // 원시값만 의존성으로 사용

 

콜백 함수의 처리

interface Props {
    onDataChange: (data: any) => void;
}

const DataComponent: React.FC<Props> = ({ onDataChange }) => {
    // 콜백을 props로 받는 경우
    useEffect(() => {
        const data = processData();
        onDataChange(data);
    }, [onDataChange]); // 부모에서 useCallback 사용 권장
};

// 부모 컴포넌트
const Parent = () => {
    const handleDataChange = useCallback((data) => {
        console.log(data);
    }, []); // 메모이제이션된 콜백

    return <DataComponent onDataChange={handleDataChange} />;
};

이러한 해결 방법들을 통해 useEffect의 의존성 경고를 효과적으로 해결할 수 있습니다. 특히 중요한 포인트는:

  1. 가능한 한 useEffect 내부로 함수를 이동
  2. 외부 함수가 필요한 경우 useCallback 사용
  3. 객체나 배열 대신 원시값을 의존성으로 사용
  4. props로 받는 콜백은 부모 컴포넌트에서 useCallback 사용

이러한 원칙들을 따르면 불필요한 리렌더링을 방지하고 안정적인 컴포넌트를 구현할 수 있습니다.