[React] React Basic - (3) LifeCycle API

React Basic - (3) LifeCycle API

Lifecycle API

컴포넌트가 브라우저에서 나타날때, 사라질때, 그리고 업데이트 될 때, 호출되는 API

Component 생성

  • constructor : Component 생성자 함수
  • componentDidMount() : 컴포넌트가 화면에 나타나게 됐을 때 호출

Component 업데이트

  • static getDerivedStateFromProps() : props 로 받아온 값을 state 로 동기화 하는 작업을 해줘야 하는 경우에 사용
  • shouldComponentUpdate() : 컴포넌트를 최적화하는 작업에서 사용됨

⇒ 기본적으로 true를 반환하지만, 특정 조건에 따라 false를 반환하도록 변경하면 불필요한 리렌더링을 방지해준다. (render()함수를 호출하지 않음)

  • getSnapshotBeforeUpdate() : DOM 변화가 일어나기 직전의 DOM 상태를 가져옴.
  • componentDidUpdate()

Component 제거

  • componentWillUnmount() : 등록된 이벤트 제거

Counter.js

import React, {Component} from 'react';

class Counter extends Component {
    // Component의 state를 정의할 때는 class field를 사용함
    state = {
        number: 0
    }

    // 생성자
    constructor(props) {
        super(props);
        console.log('constructor');
    }

    // 컴포넌트가 화면에 나타나게 됐을 때 호출
    componentDidMount() {
        console.log('componentDidMount');
    }

    // 불필요한 리렌더링을 방지
    shouldComponentUpdate(nextProps, nextState) {
        console.log('shouldComponentUpdate');
        // number가 5의 배수이면 리렌더링 되지 않음
        if(nextState.number%5==0) return false;
        return true;
    }

    componentDidUpdate(prevProps, prevState) {
        console.log('componentDidUpdate');
    }
 
    // Component에 method 작성
    handleIncrease = () => {
        const {number} = this.state;
        this.setState({
            number : number+1
        });
    }
    handleDecrease = () => {
        const {number} = this.state;
        this.setState({
            number : number-1
        });
    }
    render() {
        console.log('render');
        return (
            <div>
                <h1>Counter :
                </h1>
                <div>Value : {this.state.number}</div>
                <button onClick={this.handleIncrease}>+</button>
                <button onClick={this.handleDecrease}>-</button>
            </div>
        )
    }
}
export default Counter;

Component 에 에러가 발생하면?

  • componentDidCatch() : 에러가 발생하면 실행되는 함수
componentDidCatch(error, info) {
  this.setState({
    error: true
  });
}

⇒ state.error를 true로 설정 후, render() 함수에서 if문을 이용하여 에러 catch

Counter.js

import React, {Component} from 'react';

const Problematic = () => {
    // error를 throw하는 구문
    throw (new Error('버그 발생 !'));
    return (
        <div></div>
    );  
};

class Counter extends Component {
    state = {
        number: 0
    }

    handleIncrease = () => {
        const {number} = this.state;
        this.setState({
            number : number+1
        });
    }
    handleDecrease = () => {
        const {number} = this.state;
        this.setState({
            number : number-1
        });
    }
    // 자식 컴포넌트에서 발생한 에러를 잡는 함수
    componentDidCatch(error, info) {
        this.setState({
            error : true
        });
    }

    render() {
        // error가 true 이면 Element return 
        if(this.state.error) return (<div>error 발생 !</div>);
        return (
            <div>
                <h1>Counter :
                </h1>
                <div>Value : {this.state.number}</div>
                {/* number가 4이면 Problematic 컴포넌트를 렌더링함 */}
                { this.state.number==4 && <Problematic/>}
                <button onClick={this.handleIncrease}>+</button>
                <button onClick={this.handleDecrease}>-</button>
            </div>
        );
    }
}
export default Counter;

Rendering에서 발생하는 에러를 방지하기 위해서..

  1. 존재하지 않는 함수 호출 방지
  2. 존재하지 않는 객체나 배열 호출 방지

ex)

error

this.props.object.value; // object is undefined
this.props.array.length; // array is undefined

solution

render() {
  if (!this.props.object || !this.props.array || this.props.array.length ===0) return null;
  // object 나 array 를 사용하는 코드
}

or

static defaultProps = {
    onIncrement: () => console.warn('onIncrement is not defined'),
    object: {},
    array: []
  }