React.js에서 useEffect 재렌더링을 적절하게 방지

Feb 07 2023
Backstory 저는 React에서 Firebase를 사용하여 앱을 구축하고 있었는데, 그날 읽기 한도가 50k에 도달했다는 사실을 알고 놀랐습니다. 내 앱이 내 컴퓨터에서만 로컬로 실행되고 내가 유일한 사용자였기 때문에 도대체 어떻게 그게 가능한지 알 수 없었습니다.

뒷이야기

저는 React에서 Firebase를 사용하여 앱을 구축하고 있었는데, 그날의 50k 읽기 한도에 도달했다는 사실에 놀랐습니다. 내 앱이 내 컴퓨터에서만 로컬로 실행되고 내가 유일한 사용자였기 때문에 도대체 어떻게 그게 가능한지 알 수 없었습니다.

내가 직면한 문제는 상태 변수를 변경하는 비동기 호출을 수행할 때 내 구성 요소를 다시 마운트하는 것과 관련이 있습니다.

다음은 useEffect.

import {useEffect} from 'react'
function Example() {
    const [vehicles, setVehicles] = useState([])
    const vehiclesRef = collection(db, 'vehicles')

    useEffect(() => {
        const getVehicles = async () => {
            const data = await getDocs(vehiclesRef)
            setVehicles(data.docs.map( doc => ( // memory leaks 
                        {
                            ...doc.data(), 
                            id:doc.id 
                        }
                    )
                )
            )
        }

        getVehicles()
    },[vehicles])       
}

경고: 마운트 해제된 구성 요소에서 React 상태 업데이트를 수행할 수 없습니다. 이것은 작동하지 않지만 애플리케이션의 메모리 누수를 나타냅니다. 수정하려면 useEffect 정리 함수에서 모든 구독 및 비동기 작업을 취소하세요.

를 호출하면 setState구성 요소가 다시 렌더링되어 해당 값의 변경 사항으로 DOM을 업데이트합니다. 즉, setVehicles()구성 요소가 마운트될 때마다 계속해서 초기화됩니다. 이렇게 하면 무한 재렌더링 루프가 발생하여 값비싼 함수 호출을 할 때 많은 비용이 듭니다.

내가 고친 방법은 다음과 같습니다.

import {useEffect, useRef} from 'react'
function Example() {
    const [vehicles, setVehicles] = useState([])
    const vehiclesRef = collection(db, 'vehicles')

    useEffect(() => {
        let isMounted = true

        const getVehicles = async () => {
            const data = await getDocs(vehiclesRef)
            
            if(isMounted){
                setVehicles(data.docs.map( doc => (
                            {
                                ...doc.data(), 
                                id:doc.id 
                            }
                        )
                    )
                )
            }
        }

        getVehicles()

        console.log(vehicles)

        return () => { isMounted = false }
    }, [vehicles]) 
}

이면 구성 요소가 다시 마운트될 때 해당 값이 true로 설정될 때까지 코드가 실행되지 않습니다 isMounted .false

도움이 되었기를 바랍니다!

레벨업 코딩

우리 커뮤니티의 일원이 되어 주셔서 감사합니다! 가기 전에:

  • 스토리 박수치고 작가 팔로우
  • 레벨업 코딩 출판물 에서 더 많은 콘텐츠 보기
  • 팔로우: 트위터 | 링크드인 | 뉴스 레터