Frontend/React

React | 컴포넌트의 생명주기, useEffect

hyuga_ 2024. 1. 5. 11:01

Life cycle: 마운팅 - 업데이트 - 언마운팅

  • Mount: 컴포넌트가 화면에 나타나는 것
  • Update: 컴포넌트가 업데이트되어 리렌더되는 것
  • Unmount: 컴포넌트가 화면에서 사라지는 것

 

useEffect로 생명주기 핸들링하기 

리액트는 라이프 사이클마다 실행할 수 있는 메서드를 가지고 있는데, 이들은 함수형이 아니라 클래스형 컴포넌트에서만 사용할 수 있다.

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

 

그러나 앞서 배웠듯 이러한 메서드들은 리액트 훅을 통해 함수형 컴포넌트에서도 사용 가능해졌다. 

컴포넌트 생명주기를 핸들링하는 기능은 useEffect 라는 훅을 통해 구현된다. 

 

첫번째 파라미터에는 콜백함수(Clean-up 함수)가 들어간다. 

두번째 파라미터는 Deps 또는 Dependency Array (의존성 배열) 라고 부른다. 

이 Deps 안에 있는 값 중 하나라도 변화하면 첫번째 파라미터인 콜백함수가 계속 수행된다. 

 

컴포넌트는 언제 업데이트 될까?

일반적으로 다음 세가지 상황 중 하나일 것이다.

  • State 변경되거나
  • 부모에게서 내려받는 Props가 바뀌거나
  • 부모 컴포넌트가 리렌더링되거나 (그럼 자식들도 리렌더링 되므로)

 

import React, {useEffect, useState} from 'react';

// 언마운트 시 대응하는 용도로 useEffect 사용하기 - return 값으로 함수 반환하기
const UnmountTest = () => {
    useEffect(()=>{
        console.log("언마운트 테스트 Mount!")
        
        return (() => {
            // useEffect의 리턴 함수는 Unmount 될 때 호출됨
            console.log("언마운트 테스트 Unmount!")
        })
    },[])

    return (
        <div> Unmount Testing Component </div>
    )
}

const Lifecycle = () => {
    const [count, setCount] = useState(0);
    const [text, setText] = useState("");

    // 마운트 시 대응하는 용도로 useEffect 사용하기 - deps로 빈 배열 전달
    useEffect(()=> {
        console.log("Mount!");
    },[])

    // 컴포넌트 업데이트 시 대응하는 용도로 useEffect 사용하기 - deps 전달 X
    useEffect(()=>{
        console.log("Update!");
    })

    // 특정 state 변화에만 대응하는 용도로 useEffect 사용하기 - deps에 해당 state 전달
    useEffect(()=>{
        console.log(`Count updated: ${count}`);
        if (count > 5){
            alert("카운트가 5를 넘었습니다. 초기화를 수행합니다");
            setCount(0);
        }
    },[count])

    // 토글 구현하기 for Unmount test
    const [isVisible, setIsVisible] = useState(false);
    const toggle = () => setIsVisible(!isVisible);
    /* 
    아래 return 에서 단락회로 평가 - {isVisible && <UnmountTest />} -를 통해 토글 기능 구현 가능
    isVisible이 true이면, 뒤에 값을 반환받아 읽어야 함.
    근데 읽는 순간 화면에 렌더링 됨. (true 이기도 하고)
    */
    
    return (
    <div style={{ padding: 20 }}>
        <div>
            <button onClick={toggle}> on/off </button>
            {isVisible && <UnmountTest />} 
        </div>
        <div>
            {count}
            <button onClick={()=> setCount(count+1)}> + </button>
        </div>
        <div>
            <input value={text} onChange={(e) => setText(e.target.value)} />
        </div>
    </div>)
}

export default Lifecycle;

 

 

 

useEffect 사용 예시

  • 버에서 데이터를 가져오거나 API 호출을 하는 경우, 컴포넌트가 마운트된 후에 useEffect를 사용하여 데이터를 가져온다.
  • 외부 데이터 소스를 가져오고, 이를 취소하는 경우, useEffect에서 데이터를 가져오고 반환된 클린업 함수에서 이를 취소한다.
  • 컴포넌트가 마운트된 후 DOM을 직접 조작해야 하는 경우, useEffect 내에서 이를 수행할 수 있다.