본문 바로가기
Understanding React.js

React Hook_useEffect

by Luciditas 2023. 4. 10.
728x90

Component의 Lifecycle

모든 Component는 1) 생성될 수 있고, 2) 재렌더링이 일어날 수 있고, 3) 삭제될 수도 있다.

1) ~ 3)의 사이클을 Component의 Lifecycle이라고 한다.

React에서 Component의 Lifecycle이 중요한 이유는 Component의 Lifecycle 중간 중간에 간섭이 가능하기 때문이다.

예를 들어보자.

'A라는 Component가 등장하기 전에 이 것 좀 해줘'

'A Component가 사라지기 전에  저 것 좀 해줘'

'A Component가 업데이트 된 후에 그 것 좀 해줘'

이렇게 Lifecycle에 간섭이 가능하다.

 

useEffect()의 기본적인 사용

Lifecycle Hook 중 하나가 바로 useEffect다.

 

import { useState, useEffect } from 'react';

function Component () {
    useEffect(() => {
        console.log ('hello world')
    });
    return (결과값)
};

 

최상단에서 useEffect를 import한 후 callback 함수로 작성하면된다.

이러면 Component가 Mount되고 Update될 때 실행된다.

 

useEffect()의 특징

useEffect()안에 작성한 코드는 html이 렌더링 된 이후에 동작한다.

 

아래와 같은 코드가 있다고 생각해보자.

function HundredBillion () {
    '반복문을 1000억번 돌리는 코드'
    return(생략)
}

만약 useEffect()없이 위 함수를 작성한다면 리액트는 위 함수 HundredBillion을 1천억번 돌린 후 html을 렌더링 할 것이다.

그렇게 되면 렌더링하는데 시간이 오래 걸리지 않을까?

그렇다면 아래의 코드와 같이 작성한다면 어떻게 될까?

function HundredBillion () {
    useEffect(()=>{
        '반복문을 1000억번 돌리는 코드'
    });
    return (생략)
}

이렇게 useEffect()를 이용하여 코드를 작성하면 html을 렌더링하고 나서 반복문을 돌려준다.

즉 특정 코드의 실행 시점을 조절 할 수 있게된다.

만약 조금이라도 html 렌더링이 빠른 사이트를 만들어야 한다면 html 렌더링과 관련된 코드를 제외한 코드들은 useEffect()안에 넣으면 좋을 것이다.

특히 서버에서 데이터를 가져오는 작업, 타이머를 작성하는 작업, 오래 걸리는 반복 연산 등에 useEffect()가 많이 사용된다고 한다.

 

useEffect()에 넣을 수 있는 실행 조건

useEffect()의 두 번째 파라미터로 []를 넣을 수 있다.

useEffect(()=>{실행할코드}, [change])

[]안에는 변수나 state 등을 넣을 수 있다.

그렇게 하면 [] 안에 있는 변수나 state가 변경될 때만 useEffect() 안에 있는 코드를 실행시켜준다.

위의 코드를 예로들면 위 코드는 change라는 변수가 변경될 때만 useEffect() 내부의 코드를 실행시킨다.

[]안에는 여러 state를 저장할 수도 있고 아무것도 적지 않을 수도 있다.

만약 []에 아무런 값도 존재하지 않는다면 처음 Mount될 때만 1회 실행시켜 준다.

 

Cleanup Function

useEffect()가 동작하기 전에 특정 코드를 실행하고 싶다면 아래와 같은 코드 안에 넣어줄 수 있다.

return () => {}

이걸 useEffect()에서 Cleanup Function이라고 한다.

Component가 재렌더링이 될 때 useEffect()내의 기존 코드를 자체적으로 싸악 정리해준다고 이해하면 될 것 같다.

 

useEffect()안에서 어떻게 작동할까?

useEffect(()=>{
    // 2 번째로 실행되는 코드
    return ()=>{
        // 1 번째로 실행되는 코드
    }
}, [change]);

이런 코드가 있다고 가정하자.

이 코드에서는 return () => {}이 먼저 실행되고 useEffect()가 실행된다.

 

Cleanup Function의 기능

setTimeout()을 예로 들어보자.

setTimeout()을 쓸 때마다 브라우저 안에 있는 타이머가 하나씩 추가된다.

여기서 useEffect()안에 setTimeout()을 작성했기 때문에 컴포넌트가 Mount 될 때마다 실행될 것이다.

그럼 천 번 만 번 setTimeout()을 쓸 면 천 번 만 번 타이머가 생성될 것이다.

이럴 때 Cleanup Function이 해결책이 될 수 있지 않을까?

useEffect() 내부에서 타이머를 생성하기 전에 기존 타이머가 있다면 기존 타이머는 지워 달라는 코드를 짜면 될 것이다.

useEffect(() => {
    let a = setTimeout(()=>{setAlert(false)}, 2000)
},[])

이렇게 작성하면 컴포넌트가 mount될 때마다 타이머가 생성되니 아래와 같이 코드를 하나 추가해보자.

useEffect(()=>{
    let a = setTimeout(()=>{setAlert(false)}, 2000)
    return () => {clearTimeout(a)}// 여기서 clearTimeout은 JS 내장 메서드이다.
},[])

이렇게 Cleanup Function을 활용해서 clearTimeout 함수를 호출한다면 Component가 mount 될 때 기존에 타이머가 있다면 원래 있던 타이머는 삭제될 것이다. 

 

** 추가 참고 사항

1) Cleanup Function은 타이머 제거, soket 연결 요청 제거, ajax 요청 중단 등의 코드가 주로 들어간다.

2) Component가 unmount될 때 Cleanup Function이 1회 실행된다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90