[스터디]리액트를 다루는 기술 – 컴포넌트의 라이프사이클 메서드

라이플사이클 메서드

  • render() : 컴포넌트의 모양을 정의
  • constructor(props) : 컴포넌트의 생성자
  • getDerivedStateFromProps(nextProps, prevState) : 컴포넌트가 마운트될 때와, 업데이트될 때 호출. props롤 받아온 값을 state에 동기화 시키는 용도
  • componentDidMount() : 첫 렌더링 이후 실행
  • shouldComponentUpdate(nextProps, nextState, nextContext) : props, state 변경할 때, 리렌더링을 할 지 말 지를 결정하는 메서드
  • getSnapshotBeforeUpdate(prevProps, prevState) : render에서 만들어진 결과물이 브라우저에 반영되기 직전에 호출
  • componentDidUpdate(prevProps, prevState, snapshot) : 리렌더링을 완료한 후 실행
  • componentWillUnmount() : 컴포넌트를 DOM에서 제거할 때 실행
  • componentDidCatch() : 컴포넌트 렌더링 도중 에러가 발생할 경우 사용
// LifeCycleSample.js
import React, { Component } from 'react';

class LifeCycleSample extends Component {
    state = {
        number: 0,
        color: 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, nextContext) {
        console.log('shouldComponentUpdate');
        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>
                <h1 style={style} ref={ref => (this.myRef = ref)}>
                    {this.state.number}
                </h1>
                <p>color : {this.state.color}</p>
                <button onClick={this.handleClick}>더하기</button>
            </div>
        );
    }
}

export default LifeCycleSample;


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

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>
                <button onClick={this.handleClick}>랜덤 색상</button>
                <LifeCycleSample color={this.state.color} />
            </div>
        );
    }
}

export default App;

에러 잡아내기

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

class ErrorBoundary extends Component {
    state = {
        error: false
    };
    componentDidCatch(error, errorInfo) { // 에러가 발생하면 잡힌다.
        this.setState({
            error : true
        })
        console.log({error, errorInfo});
    }

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

export default ErrorBoundary;

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

class LifeCycleSample extends Component {
    state = {
        number: 0,
        color: 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, nextContext) {
        console.log('shouldComponentUpdate');
        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>
                {this.props.my.value}  // 존재하지 않는 값을 호출하여 에러발생
                <h1 style={style} ref={ref => (this.myRef = ref)}>
                    {this.state.number}
                </h1>
                <p>color : {this.state.color}</p>
                <button onClick={this.handleClick}>더하기</button>
            </div>
        );
    }
}

export default LifeCycleSample;


// 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>
                <button onClick={this.handleClick}>랜덤 색상</button>
                <ErrorBoundary>
                    <LifeCycleSample color={this.state.color} />
                </ErrorBoundary>
            </div>
        );
    }
}

export default App;

You may also like...

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다