[React/Udemy] 강의 내용 정리 Section #10 - useEffect()

ZenTechie·2023년 4월 20일
0

Udemy

목록 보기
1/4


Side Effect란 무엇인가?

React Component가 화면에 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 칭한다. 함수가 실행되면서 함수 외부에 존재하는 값이나 상태를 변경시키는 등의 행위를 칭한다.
예를 들어, 키 입력을 듣고 입력된 데이터를 저장하는 것, Form의 유효성을 검사하는 것, http Request를 보내는 것, 브라우저 저장소에 무언가를 저장하는 것, 코드에서 타이머나 간격을 설정하는 것, 네트워크를 통해 데이터를 송신하는 것 등이 포함된다.
즉, 어떤 액션에 대한 응답으로 실행되는 액션이 있다면 그것은 Side-Effect이다.

Side Effect 처리하기

React에는 Side Effect를 처리할 수 있는 useEffect() 함수를 제공한다.

useEffect() 사용하기

useEffect(() => {...}, [ dependencies ])
useEffect에는 2가지 인자가 있다.
1. () => {...} : 특정 의존성이 변할 때 컴포넌트의 평가가 이루어진 후에 실행되어야 하는 코드가 들어가는 곳 -> side effect 코드를 여기에 선언한다.
즉, render이후 동작하게 될 함수를 넣는다.

  1. [ dependencies ] : effect의 의존성 코드가 들어가는 곳(즉, 여기에 들어가는 코드가 변할 때 side effect 코드가 실행된다.)
    즉, 동작 시점을 정할 수 있도록 하는 의존값을 가지고 있는 배열을 넣는다.

dependencies(종속성)에 무엇이 들어가야 하나?

간단히 말해서, effect 함수에서 사용하는 모든 "것들"을 추가해야 한다.
구성 요소(또는 일부 상위 구성 요소)가 다시 렌더링 되어 이러한 "것들"이 변경될 수 있는 경우, 그렇기 때문에 컴포넌트 함수에 정의된 변수나 상태, 컴포넌트 함수에 정의된 props 또는 함수는 종속성으로 추가되어야 한다.

다음의 예시 코드를 살펴보자.

import { useEffect, useState } from 'react';
 
let myTimer;
 
const MyComponent = (props) => {
  const [timerIsActive, setTimerIsActive] = useState(false);
 
  const { timerDuration } = props; // using destructuring to pull out specific props values
 
  useEffect(() => {
    if (!timerIsActive) {
      setTimerIsActive(true);
      myTimer = setTimeout(() => {
        setTimerIsActive(false);
      }, timerDuration);
    }
  }, [timerIsActive, timerDuration]);
};

이 예시에서,

timerIsActive 는 종속성으로 추가되었다.
왜냐하면 구성 요소가 변경될 때 변경될 수 있는 구성 요소 상태이기 때문이다.
(예: 상태가 업데이트되었기 때문에)

timerDuration 는 종속성으로 추가되었다.
왜냐하면 해당 구성 요소의 prop 값이기 때문이다
따라서 상위 구성 요소가 해당 값을 변경하면 변경될 수 있다.
(이 MyComponent 구성 요소도 다시 렌더링되도록 함).

setTimerIsActive 는 종속성으로 추가되지 않는다.
왜냐하면, 예외 조건이기 때문이다.(상태 업데이트 기능을 추가할 수 있지만 React는 기능 자체가 절대 변경되지 않음을 보장하므로 추가할 필요가 없다.)

myTimer 는 종속성으로 추가되지 않는다.
왜냐하면 구성 요소 내부 변수가 아니기 때문이다.
(즉, 어떤 상태나 prop 값이 아님)

setTimeout 은 종속성으로 추가되지 않는다.
왜냐하면 내장 API이기 때문이다. (브라우저에 내장)
React 및 구성 요소와 독립적이며 변경되지 않는다.

dependencies에 따른 다른 결과

1. dependencies 없이

useEffect(() => {
  console.log("I'm UseEffect!");
})

dependencies 에 아무런 값도 넣지 않으면, 모든 re-render 상황에서 useEffect()가 실행된다.(모든 컴포넌트 렌더링 주기 이후에 실행된다. 첫 렌더링도 포함.)

2. dependencies에 빈 배열

useEffect(() => {
  console.log("I'm UseEffect!");
}, [])

dependencies 에 빈 배열을 넣는다면, 초기 렌더링될 때 1번만 useEffect()가 실행된다.

3. dependencies에 특정 값 지정

useEffect(() => {
  console.log("I'm UseEffect!");
},  [ isLogin ])

dependencies에 특정 값을 넣는다면, 특정 값이 변할 때만 useEffect()가 실행된다.

useEffect()에서 Cleanup 함수 사용하기

Cleanup 함수 란, useEffect Hook 내에서 return되는 함수이다.
컴포넌트가 사라질 때(컴포넌트가 재사용 될 때, unmount) 또는 특정 값이 변경되기 전에 실행할 작업 을 지정할 수 있다.

useEffect(() => {
  // 실행할 함수
  
  // clean-up 함수
  return () => { ... } 
}, [ dependencies ]);

즉, clean-up 함수는 다음 2가지 상황에서 사용할 수 있다.
1. 컴포넌트가 unmount될 때(컴포넌트가 재사용 될 때) : useEffect(() => {...}, [])
2. 특정 값을 변경하기 전 : useEffect(() => {...}, [특정 값])

Clean-up 함수 사용 시 작동 흐름

Re-rendering -> Clean-up 코드 실행 -> 사이드 이펙트 내부 코드 수행

예시 코드를 보자.

useEffect(() => {
  // 사이트 이펙트 내부 코드(실행시킬 함수)
  setTimeout(() => {
    console.log('Checking form validity!');
    setFormIsValid(
      enteredEmail.includes('@') && enteredPassword.trim().length > 6
    );
  }, 500);
  
  // clean-up 함수
  return () => {
    console.log('CLEANUP');
  };
}, [enteredEmail, enteredPassword]);

위 코드는, 이메일과 비밀번호를 입력하는 인풋을 감싸는 폼이 있고, 해당 인풋에 변화가 감지되면 수행되는 useEffect() 코드이다.

실행 결과

  1. CLEANUP
  2. Checking form validity!
profile
데브코스 진행 중.. ~ 2024.03

0개의 댓글