DEVELOPMENT/react

8. 라이프 사이클과 리액트 개발자 도구

Tiny Commit 2024. 12. 23. 11:03

 

1. 리액트 컴포넌트와 라이프 사이클

리액트 컴포넌트 = 라이프 사이

 

Mount: 컴포넌트를 페이지에 처음 렌더링 할 때

Update: State나 Props의 값이 바뀌거나 부모 컴포넌트가 리렌더해 지신도 리렌더 될때

Unmount: 더 이상 페이지에 컴포넌트를 렌더링하지 않을 때

 

라이프 사이클을 이용하면 컴포넌트가 처음 렌더링할 때 특정 동작을 하도록 만들거나, 업데이트힐 때 적정한지 검사하거나, 페이지에서 사라질 때 메모리를 정리하는 등 여러 유용한 작업을 할 수 있다. 이를 라이프 사이클 제어라고 하며, 리액트 훅의 하나인 uesEffect를 이용하여 제어할 수 있다.

 

 

 

 

 

2. useEffect

useEffect: 값이 변결할 때마다 특정 코드를 실행하는 리액트의 훅 ("특정 값을 검사한다.")

useEffect를 사용하면 컴포넌트의 State값이 바뀔 때마다 변경된 값을 콘솔에 출력할 수 있습니다.

1. 하나의 값 검사하기

App컴포넌트에서 State변수 count의 값이 바뀌면, 변경된 값을 콘솔에 출력하겠습니다.

useEffect의 용법
2useEffect(callback, [deps])
3          콜백 함수 의존성 배열

 

두번째 인수로 전달되는 의존성 배열의 요소값이 변경되면 첫 번째 인수로 전달한 콜백함수를 실행합니다.

 

import "./App.css";
import { useState, useEffect } from "react"; 
import Controller from "./component/Controller";
import Viewer from "./component/Viewer";

function App() {
  const [count, setCount] = useState(0);
  const handleSetCount = (value) => {
    setCount(count + value);
  };

  useEffect(() => { // useEffect를 호출하고 두 개의 인수를 전달합니다. 첫 번째 인수로 콜백 함수를, 두 번째 인수로 배열을 전달
    console.log("count 업데이트: ", count);
  }, [count]);

  return (
    <div className="App">
      <h1>Simple Counter</h1>
      <section>
        <Viewer count={count} />
      </section>
      <section>
        <Controller handleSetCount={handleSetCount} />
      </section>
    </div>
  );
}
export default App;

 

코드에서 의존성 배열요소에 State변수 count가 있어서 이 값이 바뀌면 callback함수가 실행됩니다. 이 함수는 "count 업데이트"라는 문자열과 함께 State값을 출력합니다.

이때 "count 업데이트: 0"이 콘솔에 출력되는데, State값을 초기화 할 때도 useEffect가 이 변화를 감지하기 때문입니다.

 

 

 

useEffect를 이용하면 특정 값이 바뀔 때마다 원한는 코드를 실행하도록 만들 수 있습니다.

 

 

 

2. 여러 개의 값 검사하기

배열요소가 여러개 있으면 요소 중 하나가 변경되면 useEffect는 콜백함수를 실행합니다.

 

State변수 count외에 임ㅁ수 입력폼 추가하고, text라는 State변수를 하나 더 만들겠습니다.

//src/App.js
import "./App.css";
import { useState, useEffect } from "react"; 
import Controller from "./component/Controller";
import Viewer from "./component/Viewer";


function App() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState(""); // State변수 text만들기
b
  const handleSetCount = (value) => {
    setCount(count + value);
  };
  const handleChangeText = (e) => { // onChange 이벤트 핸들러 함수 만들기
    setText(e.target.value);
  };b

  useEffect(() => {
    console.log("업데이트: ", text, count);
  }, [count, text]);

  return (
    <div className="App">
      <h1>Simple Counter</h1>
      <section>
        <input value={text} onChange={handleChangeText} /> 
      </section>b
      <section>
        <Viewer count={count} />
      </section>
      <section>
        <Controller handleSetCount={handleSetCount} />
      </section>
    </div>
  );
}
export default App;

 

 

 

 

 

 

3. useEffect로 라이프 사이클 제어하기

useEffec의 마운트 시점말고 Update시점에서만 콜백함수를 실행하겠습니다.

즉, 페이지에 처음 렌더링할 떄는 콜백함수를 실행하지 않고 리렌더될 때만 실행하겠다는 뜻입니다.

 

import "./App.css";
import { useRef, useState, useEffect } from "react";
import Controller from "./component/Controller";
import Viewer from "./component/Viewer";

function App() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");
  const didMountRef = useRef(false); // 페이지에 마운트했는지 판단하는 변수 didMountRef

  const handleSetCount = (value) => {
    setCount(count + value);
  };
  const handleChangeText = (e) => {
    setText(e.target.value);
  };

  useEffect(() => { // 의존성 배열로 아무것도 전달하지 않았으므로, 콜백 함수는 마운트 시점에도 실행되어야 합니다. 
    if (!didMountRef.current) { // 마운트 시점에는 콘솔에 ‘컴포넌트 업데이트’ 문자열을 출력하지 않도록
      didMountRef.current = true;
      return;
    } else {
      console.log("컴포넌트 업데이트!");
    }
  });

  return (
    <div className="App">
      <h1>Simple Counter</h1>
      <section>
        <input value={text} onChange={handleChangeText} /> 
      </section>
      <section>
        <Viewer count={count} />
      </section>
      <section>
        <Controller handleSetCount={handleSetCount} />
      </section>
    </div>
  );
}
export default App;

 

 

 

 

 

 

4. 컴포넌트의 마운트 제어하기

컴포넌트 마운트 시점에서 "컴포넌트의 마운트를 제어한다."

 

import "./App.css";
import { useRef, useState, useEffect } from "react";
import Controller from "./component/Controller";
import Viewer from "./component/Viewer";

function App() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");
  const didMountRef = useRef(false); 

  const handleSetCount = (value) => {
    setCount(count + value);
  };
  const handleChangeText = (e) => {
    setText(e.target.value);
  };

  useEffect(() => { 
    if (!didMountRef.current) {
      didMountRef.current = true;
      return;
    } else {
      console.log("컴포넌트 업데이트!");
    }
  });

  useEffect(() => { 
    console.log("컴포넌트 마운트");
  }, []);

  return (
    <div className="App">
      <h1>Simple Counter</h1>
      <section>
        <input value={text} onChange={handleChangeText} /> 
      </section>
      <section>
        <Viewer count={count} />
      </section>
      <section>
        <Controller handleSetCount={handleSetCount} />
      </section>
    </div>
  );
}
export default App;

 

 

 

 

 

5. 컴포넌트 언마운트 제어하기

언마운트: 컴포넌트가 페이지에서 제거될 때

 

(1) 클린업

컴포넌트가 제거되기 위해서는 클린업 기능을 수행해야한다.

클린업: 특정 함수가 실행되고 종요된 후에, 미처 정리하지 못한 사항을 처리하는 일

import "./App.css";
import { useRef, useState, useEffect } from "react";
import Controller from "./component/Controller";
import Viewer from "./component/Viewer";

function App() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");
  const didMountRef = useRef(false); 

  const handleSetCount = (value) => {
    setCount(count + value);
  };
  const handleChangeText = (e) => {
    setText(e.target.value);
  };

  useEffect(() => { 
    if (!didMountRef.current) {
      didMountRef.current = true;
      return;
    } else {
      console.log("컴포넌트 업데이트!");
    }
  });

  useEffect(() => {  // 의존성 배열은 전달x
    const intervalID = setInterval(() => { // // 콜백 함수는 다시 함수 setInterval을 호출 -> 인터벌(Interval, 시간 간격)을 설정하는 함수입니다. 결과적으로 1초마다 콘솔에 문자열 깜빡 을 출력합니다.
      console.log("깜빡");
    }, 1000);
    return () => { // 컴포넌트가 언마운트하는 시점에 실행
      console.log("클린업");
      clearInterval(intervalID); // 클린업 함수는 clearInterval을 호출
    };
  });

  return (
    <div className="App">
      <h1>Simple Counter</h1>
      <section>
        <input value={text} onChange={handleChangeText} /> 
      </section>
      <section>
        <Viewer count={count} />
      </section>
      <section>
        <Controller handleSetCount={handleSetCount} />
      </section>
    </div>
  );
}
export default App;

 

 

 

정리하면 useEffect의 콜백 함수가 반환하는 함수를 클린업 함수라고 합니다. 이 함수는 콜백 함수를 다시 호출하기 전에 실행됩니다. 따라서 컴포넌트를 렌더링할 때 마다 새 인터벌을 생성하고 기존 인터벌은 삭제합니다.

 

 

 

 

(2) 클린업을 이용해 컴포넌트 언마운트 제어하기

컴포넌트가 페이지에서 사라질 대 원하는 코드를 실행하는 "컴포넌트 언마운트"

 

컴포넌트는 count값이 짝수면 특정 문자열을 페이지에 렌더링하는 조건부 렌더링 구현.

// src/component/Even.js

import { useEffect } from "react";

function Even() {
  useEffect(() => { 
    return () => {
      console.log("Even 컴포넌트 언마운트");
    };
  }, []);

  return <div>현재 카운트는 짝수입니다</div>;
}
export default Even;

 

import "./App.css";
import { useRef, useState, useEffect } from "react";
import Controller from "./component/Controller";
import Viewer from "./component/Viewer";
import Even from "./component/Event";

function App() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");
  const didMountRef = useRef(false); 

  const handleSetCount = (value) => {
    setCount(count + value);
  };
  const handleChangeText = (e) => {
    setText(e.target.value);
  };

  useEffect(() => { 
    if (!didMountRef.current) {
      didMountRef.current = true;
      return;
    } else {
      console.log("컴포넌트 업데이트!");
    }
  });

  useEffect(() => { 
    console.log("컴포넌트 마운트");
  }, []);

  return (
    <div className="App">
      <h1>Simple Counter</h1>
      <section>
        <input value={text} onChange={handleChangeText} /> 
      </section>
      <section>
        <Viewer count={count} />
      </section>
      <section>
        <Controller handleSetCount={handleSetCount} />
      </section>
      <section>
        <Viewer count={count} />
        {count % 2 === 0 && <Even />} 
      </section>
    </div>
  );
}
export default App;

 

 

 

 

 

 

 

 

 

3. 리액트 개발자 도구

State 값이 변경될 때마다 useEffect 를 수정하고 console.log로 확인한다면 이는 무척 번거로운 일이 될 겁니다. 
따라서 이번 절에서는 리액트 앱을 개발할 때 매우 유용하게 사용하는 리액트 개발자 도구(React Developer Tools)를 소개하려 합니다.

 

 

1. 리액트 개발자 도구 설치하기

크롬 브라우저 확장 프로그램

[chrome 웹스토어]:  https://chromewebstore.google.com/category/extensions?pli=1

 

Chrome Web Store

브라우저에 새로운 기능을 추가하고 탐색 환경을 맞춤설정합니다.

chromewebstore.google.com

 

[확장 프로그램 검색] -> 'React Developer Tools'입력 후 엔터 ->  [ React Developer Tools] 클릭 -> [크롭에 추가] 

 

 

 [확장 프로그램] 페이지 가져오기 

 

[세부정보] 페이지 가져오기

 

React Developer Tools의 핀을 고정

 

 

 

2. 설치확인하기

비주얼 스튜디오: npm run start

전 크롭 연동이 안되어 있어서 마이크로 엣지에 따로 확장을 설치했습니다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3. 리액트 개발자 도구의 기능 사용하기

 

(1) 컴포넌트 트리 살펴보기

[개발자 도구] -> [components탭]

App.js루트를 통해 그 아래에 Viewer, Even, Controller 3개의 자식 컴포넌트 확인 가능

 

 

(2) State모니터링하기

[components탭]에서 실시간으로 State값 모니터링 하기

앱 페이지에서 버튼을 눌러 현재 카운트를 계속해서 바꾸는지 확인합니다. 

 

 

(3) Props모니터링 하기

[components탭]에서 Viewer컨포넌트를 클릭 -> 

Viewer은 App컨포넌트가 전당한 count를 props로 받아 페이지에 렌더링

 

 

 

(4) 리렌더 하이라이트 기능 사용하기: 의미 없이 리렌더되는지 확인가능.

[components탭]에서 -> 톱니바퀴 -> View settings -> [General] 탭 -> “Highlight updates when component render.”라고 쓰여 있는 체크박스에 표시

 

 

 

 

 

 

 


 


출처 :  이정환, 『한 입 크기로 잘라먹는 리액트』, 프로그래밍인사이트(2023).

 

 

'DEVELOPMENT > react' 카테고리의 다른 글

10. 할일 관리 앱 만들기  (0) 2024.12.30
9. 리액트를 다루는 기술 - hooks  (0) 2024.12.23
7. 카운터 앱만들기  (0) 2024.11.11
6. 리액트 기본 개념 다루기 - 2  (0) 2024.11.10
5. 리액트 기본 개념 다루기 - 1  (0) 2024.11.03