본문 바로가기
React,Node,JQuery,js

[React 따라하기 #10] React 기본 함수 (life cycle)

by bryan.oh 2020. 1. 2.
반응형

 

Mounting, Updating, Unmounting.

 

- Mounting

Dom 으로 elements를 넣는것 이라고 설명되어있는데, 

간략히는 화면에 나타날 때 라고 생각해도 될거같습니다.

여기에 속하는 메소드로는

constructor() 생성자로 class 생성 시 호출 옵션
getDerivedStateFromProps() render() 호출 전 옵션
render() DOM 에 html 내보냄 필수
componentDidMount() render() 호출 후 옵션

render 는 반드시 작성해야합니다.

나머지는 정의하지 않으면 호출되지 않습니다.

만약 모두 정의했다면 표에 나온 순서대로 실행되게 됩니다.

예제로 보시죠.

webstorm 으로 만들었던 프로젝트에서 

src 아래에 js 파일을 하나 만듭니다.

lifecycletest.js

import React from 'react';

const tag = "LifeCycleTest";
class LifeCycleTest extends React.Component {
    constructor(props) {
        console.log(tag + ":constructor()");
        super(props);
        this.state = {gender:"man", age:props.age, tall:180};
    }

    render(){
        console.log(tag + ":render()");
        return (
            <div>
                <p>My tall is {this.state.tall}cm</p>
                <p>I am a {this.state.gender}.</p>
                <p>I am {this.state.age} years old.</p>
            </div>
        )
    }

    static getDerivedStateFromProps(props, state){
        console.log(tag + ":getDerivedStateFromProps()");
        return {age: state.age + 10};
    }

    componentDidMount(){
        console.log(tag + ":componentDidMount()");
        setTimeout(()=>{
            this.setState({age: this.state.age + 10});
        }, 1000)
    }
}

export default LifeCycleTest;

 

그리고 이 컴포넌트를 index.js 에서 사용합니다.

import LifeCycleTest from "./lifecycletest";

이렇게 import 하고

ReactDOM.render(<LifeCycleTest age={20} />, document.getElementById('root'))

이렇게 사용.

 

결과는

My tall is 180cm

I am a man.

I am 30 years old.  // 1초 후에 "I am 50 years old." 으로 바뀜.

이렇게 나옵니다. 40을 예상하신분도 있을텐데요.

호출되는 순서는

여기까지 "I am 30 years old." 으로 나옵니다. 그리고 1초후에 바뀌죠.

그리고 componentDidMount() 안에 있는 setTimeout 이 실행됩니다.

(1) 에서 state.age 는 +10 해서 40이 됩니다. 그리고 (4)에서 또 +10 해서 50이 됩니다.

역시 그림이 이해가 쉽죠

로그는 이렇게 찍힙니다.

LifeCycleTest:constructor()
LifeCycleTest:getDerivedStateFromProps()
LifeCycleTest:render()
LifeCycleTest:componentDidMount()
(1호 후)
LifeCycleTest:getDerivedStateFromProps()
LifeCycleTest:render()

setState 를 실행하면 render() 가 실행되는데 getDerivedStateFromProps() 만 실행됩니다.
render 후에 실행되는 componentDidMount() 는 실행되지 않습니다.

 

 

- Updating

Component 가 변경되었을 때 (state 또는 props)
관련 함수는 아래와 같습니다.

getDerivedStateFromProps() render() 호출 전 옵션
shouldComponentUpdate() update 할지말지 결정.
return : true(default) or false
true 면 update하고 false 면 안함.
옵션
render() DOM 에 html 내보냄 필수
getSnapshotBeforeUpdate() 변경 이전의 상태정보를 갖고있음
변경 후 실행.
옵션
componentDidUpdate() render() 호출 후 옵션

 

shouldComponentUpdate
위 lifecycletest.js 의 LifeCycleTest class 의 마지막에 shouldComponentUpdate 를 추가합니다.

    shouldComponentUpdate(nextProps, nextState, nextContext) {
        return false;
    }

선언하지 않으면 기본 return true 가 됩니다. 여기서는 return false 로 해봅니다.

그리고 페이지를 다시 보면 

My tall is 180cm

I am a man.

I am 30 years old.

50이 아니라 30 으로 나옵니다.

이 shouldComponentUpdate() 에서는 상태변경이 가능한지 체크를 하고 변경할지를 결정할 수 있습니다. 
예를들면 구매같은 프로세스에서 포인트를 체크해서 컨텐츠를 보여주든 결제창을 띄우든..

 

getSnapshotBeforeUpdate

변경되기 이전의 상태값을 갖고 있고 setState 후에 발생합니다.
shouldComponentUpdate 의 리턴값을 true 로 변경하고 아래 함수를 추가합니다.

    shouldComponentUpdate(nextProps, nextState, nextContext) {
        return true;
    }

    getSnapshotBeforeUpdate(prevProps, prevState) {
        document.getElementById("bf_age").innerHTML = "Before age is " + prevState.age;
    }

1초 후 결과는

My tall is 180cm

I am a man.

I am 50 years old.

Before age is 30

이렇게 나옵니다.

 

 

- Unmounting

Dom에서 element가 삭제될때 관련 함수.

componentWillUnmount() DOM 에서 삭제되면 옵션

Footer 컴포넌트를 하나 더 만들고 
LifeCycleTest class 의 render 에서 조건문으로 Footer 를 사용했다, 안했다를 결정합니다.

위 소스에서 변경할 부분만 남겨놨습니다.

import React from 'react';

const tag = "LifeCycleTest";
class LifeCycleTest extends React.Component {
    constructor(props) {
        // 생략
    }

    render(){
        console.log(tag + ":render()");
        let footer;
        if(this.state.age < 50)
            footer = <Footer />;
        return (
            <div>
                <p>My tall is {this.state.tall}cm</p>
                <p>I am a {this.state.gender}.</p>
                <p>I am {this.state.age} years old.</p>
                <span id="bf_age"></span>
                {footer}
            </div>
        )
    }

    // 생략
}

class Footer extends React.Component {
    render(){
        return <h2>hey~ footer</h2>
    }

    componentWillUnmount() {
        alert('footer will be disappeared.');
    }
}

export default LifeCycleTest;

페이지가 로드되면 state.age 가 30 이므로 footer 가 보입니다.

1초 후에 stage.age 가 50으로 바뀌고 render 가 실행 되면 if 문에서 

footer 를 선언하지 않게 되어서 Footer 가 DOM 에 나타나지 않습니다.

그럼 componentWillUnmount() 가 실행됩니다.

 

전체 소스

import React from 'react';

const tag = "LifeCycleTest";
class LifeCycleTest extends React.Component {
    constructor(props) {
        console.log(tag + ":constructor()");
        super(props);
        this.state = {gender:"man", age:props.age, tall:180};
    }

    render(){
        console.log(tag + ":render()");
        let footer;
        if(this.state.age < 50)
            footer = <Footer />;
        return (
            <div>
                <p>My tall is {this.state.tall}cm</p>
                <p>I am a {this.state.gender}.</p>
                <p>I am {this.state.age} years old.</p>
                <span id="bf_age"></span>
                {footer}
            </div>
        )
    }

    static getDerivedStateFromProps(props, state){
        console.log(tag + ":getDerivedStateFromProps()");
        return {age: state.age + 10};
    }

    componentDidMount(){
        console.log(tag + ":componentDidMount()");
        setTimeout(()=>{
            this.setState({age: this.state.age + 10});
        }, 1000)
    }


    shouldComponentUpdate(nextProps, nextState, nextContext) {
        return true;
    }

    getSnapshotBeforeUpdate(prevProps, prevState) {
        document.getElementById("bf_age").innerHTML = "Before age is " + prevState.age;
    }
}

class Footer extends React.Component {
    render(){
        return <h2>hey~ footer</h2>
    }

    componentWillUnmount() {
        alert('footer will be disappeared.');
    }
}

export default LifeCycleTest;

 

 

2019/12/27 - [HTML,Javascript] - [React 따라하기 #1] React 개발에 필요한 도구 설치

2019/12/30 - [HTML,Javascript] - [React 따라하기 #2] React 시작하기 hello world!

2019/12/30 - [HTML,Javascript] - [React 따라하기 #3] Codepen에서 실행해보기

2019/12/30 - [HTML,Javascript] - [React 따라하기 #4] ES6, js Class 에 대한 간단한 설명

2019/12/30 - [HTML,Javascript] - [React 따라하기 #5] React JSX

2019/12/30 - [HTML,Javascript] - [React 따라하기 #6] React Components(컴포넌트)

2019/12/30 - [HTML,Javascript] - [React 따라하기 #7] React Components(컴포넌트) 참조하기

2019/12/30 - [HTML,Javascript] - [React 따라하기 #8] React Props

2019/12/31 - [HTML,Javascript] - [React 따라하기 #9] React State

 

2020/01/02 - [HTML,Javascript] - [React 따라하기 #11] React Event 리액트 이벤트

728x90
반응형

댓글