ReactJS

React - ( React Hooks 2 - useEffect )

jjangsh 2024. 8. 26. 20:46

01. useEffect

 

(1) useEffect는 언제 사용할까?

useEffect는 리액트 컴포넌트가 렌더링 된 이후마다 특정 작업을 수행하도록 설정할 수 있는 Hook입니다. 쉽게 말해 어떤 컴포넌트가 화면에 보여졌을 때 내가 무언가를 실행하고 싶다면? 또는 어떤 컴포넌트가 화면에서 사라졌을 때 무언가를 실행하고 싶다면? useEffect를 사용합니다.

 

useState와 마찬가지로 React에서 제공하는 훅 (기능) 이므로, import React, { useEffect } from "react"; 로 import 해서 사용합니다.

 

(2) 코드로 보는 useEffect 기초

브라우저에서 우리가 App 컴포넌트를 눈으로 보는 순간, 즉 App 컴포넌트가 화면에 렌더링 된 이후 useEffect 안에 있는 console.log가 실행됩니다. 컴포넌트가 렌더링 된 이후 실행된다. 이게 바로 useEffect 핵심 기능입니다.

// src/App.js

import React, { useEffect } from "react";

const App = () => {

  useEffect(() => {
		// 이 부분이 실행된다.
    console.log("hello useEffect");
  });

  return <div>Home</div>;
}

export default App;

 

(3) useEffect와 리렌더링(re-rendering)

useEffect는 useEffect가 속한 컴포넌트가 화면에 렌더링 된 이후 실행됩니다. 이런 useEffect의 특징에 의해 우리가 의도치 않은 동작을 경험할 수도 있는데요.

 

다음 코드를 볼까요? input이 있고 value 라는 state를 생성하여 input과 연결시켰습니다. 이렇게 구현하고 브라우저에 input에 어떤 값을 입력하면 useEffect가 계속 실행되는 것을 볼 수 있습니다.

 

💡 아래 예제를 확인하실 때, point가 하나 더 있어요!

onChange 부분에서 setValue 아래에 console.log(value);를 찍어본다면 변경 전 값이 나올까요? 아니면 변경 후 값이 나올까요? 논리적으로는 당연히 변경 후 값이 나와야 할 것 같죠! 한번 함께 확인해 보세요.

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

const App = () => {
  const [value, setValue] = useState("");

  useEffect(() => {
    console.log("hello useEffect");
  });

  return (
    <div>
      <input
        type="text"
        value={value}
        onChange={(event) => {
          setValue(event.target.value);
		      console.log("value => ", value);
        }}
      />
    </div>
  );
}

export default App;

 

 

영상을 보면, console.log("hello useEffect"); 가 계속 실행돼서 브라우저 콘솔에 텍스트가 계속 올라오는 것을 볼 수 있습니다. 왜 input에 값을 입력한 것뿐인데, useEffect가 계속 실행되는 것일까요?

 

 

전체 흐름은 아래와 같습니다.

  1. input에 값을 입력한다.
  2. value, 즉 state가 변경된다.
  3. state가 변경되었기 때문에, App 컴포넌트가 리렌더링 된다.
  4. 리렌더링이 되었기 때문에 useEffect가 다시 실행된다.
  5. 1번 → 5번 과정이 계속 순환한다.

그래서 우리는 콘솔이 브라우저에 한 번만 찍히길 원했지만, input을 입력할 때마다 계속 찍히고 있는 것입니다. 하지만 이런 부분도 해결할 수 있습니다.

 

 

02. 의존성 배열

 

(1) 의존성 배열(dependency array) 이란?

useEffect에는 의존성 배열이라는 것이 있습니다.  쉽게 풀어 얘기하면 “이 배열에 값을 넣으면 그 값이 바뀔 때만 useEffect를 실행할게”라는 라는 것입니다.

// useEffect의 두번째 인자가 의존성 배열이 들어가는 곳 입니다.
useEffect(()=>{
	// 실행하고 싶은 함수
}, [의존성배열])

 

 

(2) 코드로 보는 의존성 배열 → 의존성 배열이 빈 배열인 경우

코드를 볼까요?

우리가 위에 보았던 코드와 동일한 코드입니다. 다만 useEffect에 의존성 배열만 추가했습니다.

일단 의존성 배열 안에는 어떠한 값도 넣지 않았습니다. 의존성 배열이 “이 배열에 값을 넣으면 그 값이 바뀔 때만 useEffect를 실행할게”라는 의미를 가진다고 했고 우리가 아무것도 넣지 않았으니 useEffect는 최초 렌더링 이후 딱 한 번만 실행되고 그 이후로는 어떤 일이 일어나도 실행이 돼서는 안 됩니다.

// src/App.js

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

const App = () => {
  const [value, setValue] = useState("");
  useEffect(() => {
    console.log("hello useEffect");
  }, []); // 비어있는 의존성 배열

  return (
    <div>
      <input
        type="text"
        value={value}
        onChange={(event) => {
          setValue(event.target.value);
        }}
      />
    </div>
  );
}

export default App;

 

 

📺의존성 배열에 빈 배열 [ ] 을 넣은 경우

영상을 보면, 우리가 input에 어떤 값을 입력하더라도, 처음에 실행된 hello useEffect외에는 더 이상 실행이 되지 않는 것을 볼 수 있습니다.  이렇게 useEffect를 사용하는데, 어떤 함수를 컴포넌트가 렌더링 된 후 단 한번만 실행하고 싶으면 의존성 배열을 [ ] 빈 상태로 넣으면 됩니다.

(3) 코드로 보는 의존성 배열 → 의존성 배열에 값이 있는 경우

빈 배열을 넣었을 때, 최초 렌더링 이후에는 useEffect가 실행되지 않는다는 것을 보셨죠? 그럼 이제 의존성 배열에 value 를 넣어보겠습니다. 우리가 배운 게 맞다면, value는 state이고 우리가 input을 입력할 때마다 그 값이 변하게 되니 useEffect도 계속 실행이 되겠죠?

// src/App.js

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

const App = () => {
  const [value, setValue] = useState("");
  useEffect(() => {
    console.log("hello useEffect");
  }, [value]); // value를 넣음

  return (
    <div>
      <input
        type="text"
        value={value}
        onChange={(event) => {
          setValue(event.target.value);
        }}
      />
    </div>
  );
}

export default App;

 

 

📺 의존성 배열에 [value] 을 넣은 경우

❓ 영상에서 콘솔이 2번 찍혀 있는 것이 보입니다. 이것은 useEffect로 인해 두 번 실행된 것이 아니라, strict mode라는 개발 환경이라서 그렇게 보이는 것입니다.

strict mode를 제거하는 방법은 main.jsx에서 <React.StrictMode> 부분을 제거하시면 됩니다!

 

 

03. clean up

(1) 클린 업 이란?

컴포넌트가 나타났을 때 (렌더링 됐을 때 = 함수 컴포넌트가 실행됐을 때) 동작하는 것은 useEffecteffect 함수입니다. 그렇다면 이제 컴포넌트가 사라졌을 때 무언가를 어떻게 실행하는지 배워볼 차례네요. 이 과정을 우리는 클린 업(clean up) 이라고 표현합니다.

 

(2) 클린 업 하는 방법

클린 업을 하는 방법은 간단합니다. useEffect 안에서 return을 해주고 이 부분에 실행되길 원하는 함수를 넣으면 됩니다.

// src/App.js

import React, { useEffect } from "react";

const App = () => {

	useEffect(()=>{
		// 화면에 컴포넌트가 나타났을(mount) 때 실행하고자 하는 함수를 넣어주세요.

		return ()=>{
			// 화면에서 컴포넌트가 사라졌을(unmount) 때 실행하고자 하는 함수를 넣어주세요.
		}
	}, [])

	return <div>hello react!</div>
};

export default App;

 

(3) 클린 업 활용해 보기

속세를 벗어나는 버튼을 만들었고 버튼을 누르면 useNavigate에 의해서 /todos로 이동하면서 속세 컴포넌트를 떠날 것입니다. 그러면서 화면에서 속세 컴포넌트가 사라질 것이고, useEffect의 return 부분이 실행될 것입니다.

// src/SokSae.js

import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";

const 속세 = () => {
  const nav = useNavigate();

  useEffect(() => {
    return () => {
      console.log(
        "안녕히 계세요 여러분! 전 이 세상의 모든 굴레와 속박을 벗어 던지고 제 행복을 찾아 떠납니다! 여러분도 행복하세요~~!"
      );
    };
  }, []);

  return (
    <button
      onClick={() => {
        nav("/todos");
      }}
    >
      속세를 벗어나는 버튼
    </button>
  );
};

export default 속세;

 

 

📺 클린업이 실행되는 영상

/  에서  /todos  잘 이동했고, 그 과정에서 clean up이 실행되었습니다.

(4) 컴포넌트 라이프사이클

리액트 컴포넌트도 태어나고, 살아가고, 죽는 생애주기가 존재합니다. 클래스형 컴포넌트를 주로 사용했을 이전 버전에서는 이 생애주기와 관련된 여러 메서드가 존재했지만 현재처럼 함수형 컴포넌트를 사용할 때는 useEffect를 주로 사용하여 핸들링합니다.

출처 : Dev Community

 

'ReactJS' 카테고리의 다른 글

React - ( React Hooks 4 - useContext )  (0) 2024.09.06
React - ( React Hooks 3 - useRef )  (1) 2024.09.05
React - ( React Hooks 1 - useState )  (0) 2024.08.23
React - ( Styled - components )  (0) 2024.08.22
React - DOM과 Virtual DOM  (0) 2024.08.21