상세 컨텐츠

본문 제목

<리액트를 다루는 기술> 7장: 컴포넌트의 라이프사이클 메서드

21-22/21-22 리액트 스타터 -2

by dev otcroz 2021. 12. 27. 13:00

본문

728x90

INDEX

7장 컴포넌트의 라이프사이클 메서드

1. 라이프사이클 메서드의 이해

● 개념

2. 라이프사이클 메서드 살펴보기

2.1 render() 함수

2.2 constructor 메서드

2.3 getDerivedStateFromProps 메서드

2.4 componentDidMount 메서드

2.5 shouldComponentUpdate 메서드

2.6 getSnapshotBeforeUpdate 메서드

2.7 comoponentDidUpdate 메서드

2.8 componentWillUnmount 메서드

2.9 componentDidCatch 메서드

 

3. 라이프사이클 메서드 사용하기

3.1 예제 컴포넌트 생성

3.2 App 컴포넌트에서 예제 컴포넌트 사용

3.3 에러 잡아내기

4. 정리

● 정리

5. Question 개념 정리 및 코드 문제

● 개념 복습 문제

● 코드 문제


1. 라이프사이클 메서드의 이해

모든 리액트 컴포넌트에는 라이프사이클 메서드가 존재한다.

컴포넌트의 수명은 페이지에 렌더링되기 전 ~ 페이지에 사라질 때까지이다. 

라이프사이클 메서드는 클래스형 컴포넌트에서만 사용할 수 있다. 

함수 컴포넌트의 경우 Hooks 기능을 사용하여 처리한다.  8장

#라이프사이클 메서드: 생명주기 메서드라고도 한다. 마운트, 업데이트, 언마운트 때에 호출되는 메서드들을 말한다.

●  개념

라이프사이클 메서드의 종류는 총 9가지이다. 

  • Will 접두사가 붙은 메서드: 어떤 작업을 작동하기 전 실행되는 메서드
  • Did 접두사 붙은 메서드: 어떤 작업을 작동한 후에 실행되는 메서드

라이프사이클은 마운트, 업데이트, 언마운트로 나뉜다.

  • 마운트: DOM이 생성되고 웹 브라우저에 컴포넌트가 나타날 때
  • 업데이트: 컴포넌트 정보 업데이트
  • 언마운트: 컴포넌트를 DOM에서 제거할 때

1. 마운트(mount)

  • constructor: 컴포넌트를 새로 만들 때마다 호출되는 클래스 생성자 메서드
  • getDerivedStateFromProps: props에 있는 값을 state에 넣을 때 사용하는 메서드
  • render: UI를 렌더링하는 메서드
  • componentDidMount: 컴포넌트가 웹 브라우저에 나타난 후 호출되는 메서드

 

2. 업데이트(update)

컴포넌트가 업데이트하는 경우

  • props, state가 바뀔 때
  • 부모 컴포넌트가 리렌더링될 때
  • this.forceUpdate로 강제 렌더링할 때

  • getDerivedStateFromProps: 업데이트 시작 전에 호출되는 메서드로, 마운트 과정에서도 호출된다. props의 변화에 따라 state 값에 변화를 주고 싶을 때 사용하는 메서드
  • shouldComponentUpdate컴포넌트 리렌더링 여부를 결정하는 메서드. true 또는 false를 반환한다. true를 반환하면 render 함수 호출, false를 반환하면 작업 중지
  • render: 컴포넌트를 리렌더링하는 메서드 
  • getSnapshotBeforeUpdate: 컴포넌트의 변화를 DOM에 반영하기 바로 직전 호출되는 메서드
  • componentDidUpdate: 컴포넌트 업데이트 과정이 끝난 후 호출되는 메서드

3. 언마운트(unmount)

  • componentWillUnmount: 컴포넌트가 웹 브라우저에 사라지기 전 호출되는 메서드

2. 라이프사이클 메서드 살펴보기

2.1  render() 함수

render() {...}

컴포넌트의 모양(웹 페이지에 보이는 UI)을 정의한다. 라이플사이클 메서드 중 필수로 사용해야하는 메서드이다.

이 메서드 안에 this.props와 this.state에 접근할 수 있고, 리액트 요소(div 태그, 컴포넌트 등)를 반환한다.

웹페이지에 아무것도 보여주고 싶지 않을 때  null 또는 false를 반환한다.

 

# this.props와 this.state는 현재 웹페이지에 보이는 값이다.

 

※주의사항

  • render() 내에서 이벤트 설정이 아닌 곳에서 setState를 사용할 수 없다.
  • 브라우저의 DOM에 접근할 수 없다.

 DOM 정보를 가져오거나 state에 변화를 줄 때에는 componentDidMount에서 처리한다.


2.2  constructor 메서드

constructor(props){...}

컴포넌트의 생성자 메서드로 컴포넌트를 만들 때 처음으로 실행되는 메서드이다.

이 메서드에서 초기 state를 설정할 수 있다.


2.3  getDerivedStateFromProps 메서드

static getDerivedStateFromProps(nextProps, prevState) {
    if(nextProps.value != = prevState.value) { 
      return { value: nextProps.value };
    }
    return null; //state 값을 변경할 필요 없을 경우, null 반환
 }

props로 받아온 값을 state에 동기화시키는 용도로 사용하는 메서드이다. 

컴포넌트가 마운트, 업데이트될 때 호출된다.


2.4 componentDidMount 메서드

componentDidMount() { ... }

마운트 과정에서 호출되는 메서드로, 컴포넌트를 만들고 첫 렌더링을 마친 후에 실행되는 메서드이다. 

메서드 내에서 js 라이브러리 또는 프레임워크 함수 호출,

이벤트 등록과 setTimeout, setInterval 네트워크 요청등의 비동기 작업을 처리한다.

 


2.5 shouldComponentUpdate 메서드

shouldComponentUpdate(nextProps, nextState) { ... }

 

props 또는 state가 변경되었을 시, 리렌더링 시작의 여부를 정하는 메서드이다.

메서드에서 true 또는 false 값을 반환하며, 컴포넌트를 만들 때 이 메서드를 생성하지 않으면 항상 true를 반환한다.

 이는 props 또는 state가 업데이트 됐을 때 항상 리렌더링 과정을 거친다.

  • true 반환: 리렌더링 과정
  • false 반환: 업데이트 과정 중지 상황에 맞는 알고리즘을 작성하여 리렌더링 방지하기 위해 false 반환(최적화)

메서드 내에서 현재 props와 state는 this.props와 this.state, 새로 설정될 props와 state는 nextProps nextState로 접근할 수 있다.


2.6 getSnapshotBeforeUpdate 메서드

getSnapshotBeforeUpdate(prevProps, prevState) {
    if(prevState.array != = this.state.array) {
    const { scrollTop, scrollHeight } = this.list
      return { scrollTop, scrollHeight };
    }
}

render에서 만들어진 결과가 웹 브라우저에 실제로 반영되기 직전에 호출되는 메서드이다.

이 메서드에서 반환되는 값은 comoponentDidUpdate 메서드의 세 번째 매개변수로 전달 받는다.

업데이트하기 직전의 값을 참고할 일이 있을 때 활용된다.

ex) 스크롤바 위치 유지


2.7 comoponentDidUpdate 메서드

componentDidUpdate(prevProps, prevState, snapshot) { ... }

리렌더링을 완료한 후 실행되는 메서드이다. 업데이트 과정이 끝난 직후라 DOM에 대한 처리가 가능하다. prevProps와 prevState를 사용하여 컴포넌트가 이전에 가졌던 데이터에 접근할 수 있다.


2.8 componentWillUnmount 메서드

componentWillUnmount() { ... }

컴포넌트를 DOM에서 제거할 때 사용하는 메서드이다. componentDidMount에서 등록한 이벤트, 타이머, 직접 생성한 DOM 등을 이 메서드로 제거한다. 


2.9 componentDidCatch 메서드

componentDidCatch(error, info) {
  this.setState({
      error: true
  });
  console.log({ error, info });
}

컴포넌트 렌더링 도중 에러가 발생했을 때 오류 UI를 보여주는 메서드이다.

  • error: 파라미터에 어떤 에러가 발생했는지 알려줌
  • info: 어느 코드에서 오류가 발생했는지에 대한 정보를 알려줌

 에러를 잡아내는 방법은?  7.3절 '에러 잡아내기' 


3. 라이프사이클 메서드 사용하기

3.1 예제 컴포넌트 생성

//LifeCycleSample.js
import { Component } from "react";

class LifeCycleSample extends Component {
  state = {
    number: 0,
    color: null,
  };

  myRef = null;

  constructor(props) {
    //컴포넌트를 처음 생성할 때 실행
    super(props);
    console.log("constructor");
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    // 마운트, 업데이트될 때 실행
    console.log("getDerivedStateFromProps");
    if (nextProps.color !== prevState.color) {
      return { color: nextProps.color };
    }
    return null;
  }

  componentDidMount() {
    // 첫 렌더링 후 실행
    console.log("componentDidMount");
  }

  shouldComponentUpdate(nextProps, nextState) {
    console.log("shouldComponentUpdate", nextProps, nextState);
    return nextState.number % 10 !== 4; //숫자의 마지막 자리 수가 4이면 => false를 반환
  }

  componentWillUnmount() {
    //컴포넌트를 DOM에서 제거할 때
    console.log("componentWillUnmount");
  }

  handleClick = () => { //4장 이벤트 핸들링
    this.setState({
      number: this.state.number + 1,
    });
  };

  getSnapshotBeforeUpdate(prevProps, prevState) {
    //브라우저에 실제로 반영되기 직전에 호출
    console.log("getSnapshotBeforeUpdate");
    if (prevProps.color !== this.props.color) {
      return this.myRef.style.color;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    //컴포넌트 업데이트 후(리렌더링 후) 실행
    console.log("componentDidUpdate", prevProps, prevState);
    if (snapshot) {
      console.log("업데이트되기 직전 색상", snapshot);
    }
  }

  render() {
    console.log("render");

    const style = {
      color: this.props.color,
    };

    return (
      <>
        <h1 style={style} ref={(ref) => (this.myRef = ref)}>
          {this.state.number}
        </h1>
        <p>color: {this.state.color}</p>
        <button onClick={this.handleClick}>더하기</button>
      </>
    );
  }
}

export default LifeCycleSample;

3.2 App 컴포넌트에서 예제 컴포넌트 사용

// App.js
import { Component } from "react";
import LifeCycleSample from "./LifeCtcleSample";

//랜덤 색상 생성
function getRandomcolor() {
  return "#" + Math.floor(Math.random() * 16777215).toString(16);
}

class App extends Component {
  state = {
    color: "#000000",
  };

  handleClick = () => {
    this.setState({
      color: getRandomcolor(),
    });
  };

  render() {
    return (
      <>
        <button onClick={this.handleClick}>랜덤 색상</button>
        <LifeCycleSample color={this.state.color}></LifeCycleSample>
      </>
    );
  }
}

export default App;
  • 첫 렌더링

  • 랜덤 색상을 누름  리렌더링

  • 더하기 버튼을 누름  리렌더링

 


3.3 에러 잡아내기

에러를 의도적으로 발생시키기 위해 다음 render()를 수정한다.

 

render()에서 오류가 발생하는 경우는?

  • 존재하지 않는 함수 사용
  • 존재하지 않는 객체의 값 조회
 // LifeCycleSample.js
 render() {
    console.log("render");

    const style = {
      color: this.props.color,
    };

    return (
      <>
        {this.props.missing.value} <!--에러 발생-->
        <h1 style={style} ref={(ref) => (this.myRef = ref)}>
          {this.state.number}
        </h1>
        <p>color: {this.state.color}</p>
        <button onClick={this.handleClick}>더하기</button>
      </>
    );
  }

 

존재하지 않는 props인 value를 조회해서 렌더링하려고 했기 때문에 오류가 발생한다.

Uncaught TypeError: Cannot read properties of undefined (reading 'value') at LifeCycleSample.render

개발자는 개발자 도구를 통해 에러의 내용을 확인할 수 있지만 사용자가 웹 서비스를 실제로 사용할 때는 흰 화면만 나타날 것이다.

 에러가 발생했다고 사용자에게 인지시켜주는 작업이 필요하다. 

 

  • ErrorBoundary.js 생성
//ErrorBoundary.js
import {Component} from 'react';

class ErrorBoundary extends Component{
    state = {
        error: false
    };

    componentDidCatch(error, info){
        this.setState({
            error: true
        });
        console.log({error, info});
    }

    render(){
        if(this.state.error) return <div>에러가 발생했습니다.</div>;
        return this.props.children;
    }


}
 //App.js
 render() {
    return (
      <>
        <button onClick={this.handleClick}>랜덤 색상</button>
        <ErrorBoundary> 
          <LifeCycleSample color={this.state.color}></LifeCycleSample>
        </ErrorBoundary>
      </>
    );
  }
}

ErrorBoundary로 LifeCyclesample을 감싸준다.

 


4. 정리

 


5. Question 개념 정리 및 코드 문제

 

● 개념 복습 문제

1. 라이프사이클은 총 3가지로 (마운트), (업데이트), (언마운트) 카테고리로 나뉜다.

2. DOM이 생성되고 웹 브라우저 상에 나타나는 과정을 (마운트)라고 한다.

3. 업데이트는 아래 경우에 웹 페이지의 업데이트 과정이 실행된다. 빈칸을 채워보자!

  • (props)이/가 바뀔 때
  • (state)이/가 바뀔 때
  • 부모 컴포넌트가 (리렌더링)될 때
  • (this.forceUpdate)로 강제로 렌더링을 트리거할 때

4. (getDerivedStateFromProps)은/는 마운트 과정과 업데이트 과정에서 호출되는 메서드로, props의 변화에 따라 state 값에도 변화를 주고 싶을 때 사용하는 메서드이다.

5. shouldComponentUpdate 메서드는 (리렌더링)을/를 시작할 지의 여부를 정하는 메서드이다. 이 메서드에서는 항상 (true) 또는 (false)를 반환하다.

6. render 함수 내에서 (this.props)와 (this.state)에 접근할 수 있으며, (리액트 요소)를 반환한다. 웹 페이지에 아무것도 보여주고 싶지 않을 때, (null) 또는 (false)를 반환하도록 처리한다

7. componentDidCatch 메서드는 컴포넌트 렌더링 도중 (에러)(이)가 발생했을 때 호출되는 메서드이다.

● 코드 문제

1. 에러를 잡아주는 에러 컴포넌트 코드를 작성하기. 에러가 발생했을 때, 호출되는 함수는 componentDidCatch 함수이다.

import { Component } from "react";

class ErrorBoundary extends Component {
  state = {
    error: false,
  };

  componentDidCatch(error, info) {

  }

  render() {

  }
}

export default ErrorBoundary;

 

2. 다음 코드는 밑의 웹 페이지에 대한 코드의 일부이다. 빈칸을 코드로 채워보자!

  constructor(props) {
    //컴포넌트를 처음 생성할 때 실행되는 메서드
  
  }

  
  static getDerivedStateFromProps(nextProps, prevState) {
    // 마운트, 업데이트될 때 실행되는 메서드
    if (                              ) { // 조건에 충족하면
      	//return을 통해 prop에서 받아온 값을 state에 동기화
    }
    return null;
  }
  
  shouldComponentUpdate(nextProps, nextState) { // 리렌더링의 여부를 결정하는 메서드
    //숫자의 마지막 자리의 수가 4이면 => false를 반환하도록 작성한다.
  }

Corner React Starter #2

Editor 유숨숨

 

728x90

관련글 더보기