오늘의 오류

[Error #1]'React Hook useEffect has missing dependencies' 에러

삐옹 2022. 5. 24. 22:04

상황

1~5까지의 랜덤한 숫자를 출력한 뒤,

false 5개로 이루어진 배열의 첫 인덱스 부터 랜덤한 숫자의 인덱스까지,

순차적으로 true로 바꾸는 로직을 useEffect에 넣으니

렌더링 후 state가 true인 요소에 조건부 스타일링이 잘 들어갔다.

그런데 찝찝한 경고문구가 하나뜬다.

WARNING! useEffect에 dependency를 빠뜨렸습니다.😛


음.. 일단 전체 코드로 시작.

 

전체 코드

const Home = ({day}) => {
    const [filled, setFilled] = React.useState([false, false, false, false, false]);
    let history = useHistory();
    const randomNum = Math.floor(Math.random() * 5);
    
    useEffect(() => {
        // 랜덤한 숫자의 인덱스만큼 false를 true로 변경 
        const map = filled.map((a, idx) => {
            const toTrue = idx <= randomNum ? filled[idx] = true : filled[idx];
            return toTrue
            })
            setFilled(map)
    }, [])

    return(
        <RowContainer>
            <Day>{day}</Day>
            <Circles>
                {/* 조건부 스타일링 */}
                {filled.map((bool, idx) => (
                    <Circle key={idx} style={
                        bool ? {backgroundColor : 'greenyellow'} : {}
                    }></Circle>
                    )
                )}
            </Circles>
            <RatingButton onClick={() => {
                history.push("/review")
            }}>평점 남기기</RatingButton>
        </RowContainer>
    )
}

[] 안에 값이 변경이 일어나면 useEffect안에 콜백함수가 실행이 된다.

그렇다면 저 dependencies라 불리는 아이를 그냥 없애보면 어떻게 될까?

dependencies가 없이는 끝없는 업데이트 지옥이 펼쳐질 것이다 라고 경고한다.

아하.

[filled, randomNum]라고 고치면 된다 이거지.

filled, randomNum 데이터가 변경이 일어날 때마다 useEffect를 실행하면 뭔가 된다고?

이해는 안되지만 되겠지 뭐.(일단 무지성 코딩해봄)

된다매;

최대 업데이트 뎁스가 초과되었다.

컴포넌트가 useEffect 안에서 setState를 불러서이기 때문이다.

아니면 dependency array가 없거나 그 중 하나가 매렌더링마다 변하기 떄문이다.

아ㅋ. useEffect안에서 setState 쓰면 안되는 거였구나~

가 아니라

Dependency array(의존성 배열)

useEffect를 사용할 떄,  최적화를 위해 두 번째 인자로 Dependency array를 줄 수 있다.
이를 쓰지않으면 렌더링 될 때마다 useEffect를 쓰겠다는 말인데, Dependency array을 주게되면
배열 안에 있는 변수가 바뀔 때만 useEffect를 실행하는게 가능해진다.
그렇게 조건부로 effect가 실행된다.

*참고로 setState는 이벤트 핸들러 안에서 비동기적으로 실행된다고 한다.

바로바로 업데이트 되는게 아니라, 이벤트가 끝날 시점에 모든 state를 모아 일괄 업데이트 한다. (for 효율성 향상)

state 업데이트 된다고 매번 DOM을 모두 리렌더링한다면 사이트에 부담이 커질 것이다.

이 부분에 대해서도 다음번에 다룰 생각이다.

 

 

[]을 

    useEffect(() => {
        // 랜덤한 숫자의 인덱스만큼 false를 true로 변경 
        const map = filled.map((a, idx) => {
            const toTrue = idx <= randomNum ? filled[idx] = true : filled[idx];
            return toTrue
            })
            setFilled(map)
    }, [])

 

 

참고사이트:

https://velog.io/@seoltang/React-setState-useEffect

 

React | setState 비동기 문제와 useEffect

setState의 비동기적 동작으로 인한 문제와 useEffect를 통한 해결

velog.io