본문 바로가기
React

라이프사이클 메서드

by 글로리. 2021. 7. 19.

라이프사이클 메서드(Lifecycle)

모든 리액트 컴포넌트에는 라이플사이클(수명주기)가 존재한다. 컴포넌트의 수명은 페이지에 랜더링 되기 전인 준비과정에서 시작하여 페이지에서 사라질 때 끝난다.

종류는 총 9가지.

  • 'Will' : 작업을 작동하기 전, 'Did' : 작업을 작동한 후

그리고 3개의 카테고리로 나뉘는데

  • 마운트 : 페이지에 컴포넌트가 나타남
  • 업데이트 : 컴포넌트 정보를 업데이트
  • 언마운트 : 페이지에서 컴포넌트가 사라짐

마운트

DOM이 생성되고 웹 브라우저상에 나타나는 것을 마운트(mount)라 한다.
호출되는 메서드

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

업데이트

4가지 경우에 업데이트를 한다.

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

호출되는 메서드

  • getDerivedStateFromProps : props에 있는 값을 state에 넣을 때 사용하는 메서드
  • shouldComponentUpdate: 컴포넌트가 리렌더링을 해야 할지 말아야 할지를 결정하는 메서드.
    true 혹은 false 값을 반환하며 false를 반환하면 작업 중지.
  • render : 컴포넌트를 리렌더링
  • getSnapshotBeforeUpdate : 컴포넌트 변화를 DOM에 반영하기 바로 직전에 호출하는 메서드
  • componentDidUpdate : 컴포넌트의 업데이트 작업이 끝난 후 호출되는 메서드

언마운트

마운트의 반대 과정으로 컴포넌트를 DOM에서 제거하는 것을 의미
호출되는 메서드

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

라이프사이클 메서드

  • render() : 컴포넌트의 모양새를 정의. 라이프사이클 메서드 중에서 유일하게 필수 메서드.
  • consructor : 컴포넌트의 생성자 메서드로 컴포넌트 만들 때 처음으로 실행됨. 이 메서드에서는 초기 state를 정할 수 있다.
  • getDerivedStateFromProps : props로 받아온 값을 state에 동기화. 마운트,업데이트 될 때 호출.
static getDerivedStateFromProps(nextProps, prevState) {
  if(nextProps.value !== prevState.value) { // 조건에 따라 특정 값 동기화
    return { value: nexProps.value };
  }
  return null; //state를 변경할 필요 없으면 null
}
  • componentDidMount : 컴포넌트를 만들고 첫 렌더링을 마친 후 실행.
  • shouldComponentUpdate : props,state가 변경됐을때, 컴포넌트가 리렌더링을 해야 할지 말아야 할지를 결정하는 메서드. true 혹은 false를 반환해야 함. 따로 생성하지 않으면 기본적으로 true 반환.
  • getSnapshotBeforeUpdate : render에서 만들어진 결과물이 브라우저에 실제로 반영되기 직전에 호출됨. 주로 업데이트하기 직전의 값을 참고할 일이 있을때 활용됨(예: 스크롤바 위치 유지)
getSnapshotBeforeUpdate(prevProps, prevState) {
  if(prevState.array !== this.state.array) {
    const { scrollTop, scrollHeight } = this.list
    return { scrollTop, scrollHeight };
  }
}
  • componentDidUpdate : 리렌더링을 완료한 후 실행. prevProps 또는 prevState를 사용하요 컴포넌트가 이전에 가졌던 데이터에 접근가능.
  • componentWillUnmount : 컴포넌트를 DOM에서 제거시 사용.
  • componentDidCatch : 렌더링 도중에 에러 발생시 먹통이 되지 않고 오류UI를 보여줌.
componentDidCatch(error, info) {
  this.setState({
    error: true
  });
  console.log({error, info});
}

라이프사이클 예제

// LifeCycleSample.js
import { thisExpression } from '@babel/types';
import React, { Component } from 'react';

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

    myRef = null; //ref를 설정할 부분
    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);
        // 숫자의 마지막 자리가 4면 리렌더링하지 않음.
        return nextState.number % 10 !== 4;
    }

    componentWillUnmount() {
        console.log('componentWillUnmount');
    }

    handleClick = () => {
        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 (
            <div>
                <h2>라이프사이클</h2>
                {/* {this.props.missing.value} */} // 에러 생성
                <h3 style={style} ref={ref => this.myRef = ref}>
                    {this.state.number}
                </h3>
                <p>color: {this.state.color}</p>
                <button onClick={this.handleClick}>
                    더하기
                </button>
            </div>
        )
    }
}

export default LifeCycleSample;

// ErrorBoundary.js. 에러잡기
import React, { 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;
    }
}


export default ErrorBoundary;

// App.js
import React, { Component } from 'react';
import LifeCycleSample from './LifeCycleSample';
import ErrorBoundary from './ErrorBoundary';

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

class App extends Component {
    state = {
        color: '#000000'
    }

    handleClick = () => {
        this.setState({
            color: getRandomColor()
        });
    }
    render() {
        return (
            <div>
                <div style={{ margin: '10px 0 0 50px' }}>
                    <button onClick={this.handleClick}>랜덤 색상</button>
                    <ErrorBoundary>
                        <LifeCycleSample color={this.state.color} />
                    </ErrorBoundary>
                </div>
            </div>
        )
    }
}

export default App;

'React' 카테고리의 다른 글

Context API  (0) 2021.08.05
Hooks  (0) 2021.07.20
컴포넌트 반복  (0) 2021.07.16
ref:DOM(클래스형컴포넌트)  (0) 2021.07.15
이벤트 핸들링  (0) 2021.07.14

댓글