ComponentDidMount

  • render()가 최초 실행 후 실행되는 메서드. (state변경으로 인한 리렌더링이 일어나도 해당 메서드는 재실행되지 않는다.)
  • 해당 메서드에 비동기 요청을 많이 한다.

[비동기 함수 중 setInterval 주의 점]

  1. setInterval을 하고 취소를 하지 않으면 해당 컴포넌트가 사라져도 무한히 실행된다.
  2. setInterval을 하고 취소를 하지 않고, 해당 컴포넌트를 제거, 생성을 반복하면 취소되지 않은 setInterval은 중첩되어 문제가 생긴다.

 

 

복습 : 라이프사이클

클래스 컴포넌트 라이프사이클

  • 생성자(constructor) → render → ref설정 → componentDidMount
  • setState / props 바뀔 때 → shouldComponentUpdate (리렌더할지말지 결정하는 함수) → render → componentDidUpdate
  • 부모가 나를 없앴을 때 → componetWillUnmount → 소멸

 

라이프사이클 관련 메서드

componentDidMount : 렌더가 처음실행되고 componentDidMount가 실행된다. (state변경으로 인한 리렌더링이 일어나도 실행되지 않는다.)

componentDidUpdate  : 리렌더링 후에는 해당 메소드가 실행된다.

componentWillUnmount : 컴포넌트가 제거되기 직전

 

 

RSP 강의 안보고 짠 전체코드

import React, {Component} from "react";

//클래스의 경우 -> constructor -> render -> ref설정 -> componentDidMount ->
// setState, props 바뀔 때 -> shouldComponentUpdate -> render -> componentDidUpdate
// 부모가 나를 없앴을 때 componentWillUnmount -> 소멸
class RSP extends Component{
    state = {
        result:'',
        score:0,
        imgCoord:0,
    }

    intervalId = null;
    position = 0;
    clickable = true;

    // 렌더가 처음실행되고 componentDidMount가 실행된다. (state변경으로 인한 리렌더링이 일어나도 실행되지 않는다.)
    componentDidMount() {
        //여기에 비동기 요청을 많이 한다.
        //만약에 setInterval을 여기다가 쓰고 취소하는 코드를 쓰지않으면 RSP 컴포넌트가 사라지더라도 계속 setInterval은 실행된다.
        //만약에 RSP 컴포넌트가 붙었다가 떼어지면 setInterval이 1번 중첩되어있지만 RSP컴포넌트가 한번 더 붙으면 setInterval이 2번 중첩되어 실행된다.
        this.startRsp();
    }

    //리렌더링 후에는 해당 메소드가 실행된다.
    componentDidUpdate(prevProps, prevState, snapshot) {
    }

    //컴포넌트가 제거되기 직전
    componentWillUnmount() {
        //componentDidMount, componentDidUpdate에서 비동기 작업을 했는데 그게 남아있으면 문제가 되기 떄문에 그런 애들을 정리해주는 것이 componentWillUnmount 이다.

        clearInterval(this.intervalId);
    }

    onClick = (e) => {
        if(!this.clickable)return; //연속클릭 방지
        this.clickable = false;
        const {target} = e;
        const id = target.id;
        clearInterval(this.intervalId);
        let userValue = 0;
        if(id === 'scissor'){
            userValue = 1; 
        }else if(id === 'paper'){
            userValue = 2;
        }

        if(userValue === this.position){
            console.log('무승부!');
            this.setState({result:'비겼습니다.'});
        } else if((userValue+1) % 3 === this.position){
            console.log('이겼어');
            this.setState((prev) => ({...prev, score:prev.score+1, result:'이겼습니다.'}));
        } else{
            console.log('졌어')
            this.setState((prev) => ({...prev, score:prev.score-1, result:'졌습니다.'}));
        }
        setTimeout(()=>{this.startRsp(); },1000)
        setTimeout(()=>this.clickable = true, 1500)
    }

    startRsp(){
        const positionArr = [0, 142, 284];
        let currentIndex = 0;
        if(this.intervalId)clearInterval(this.intervalId);
        this.intervalId = setInterval(()=>{
            this.position = currentIndex % positionArr.length;
            const pix = positionArr[this.position];
            this.setState({imgCoord:`-${pix}px`});
            //console.log(positionArr[index], this.state);
            currentIndex++;
        },100);
    }

    render() {
        const {result, score, imgCoord} = this.state;

        return(
            <>
                <div id="computer" style={{background:`url(https://en.pimg.jp/023/182/267/1/23182267.jpg) ${imgCoord} 0`}}></div>
                <button id="rock" className="btn" onClick={this.onClick}>바위</button>
                <button id="scissor" className="btn" onClick={this.onClick}>가위</button>
                <button id="paper" className="btn" onClick={this.onClick}>보</button>
                <div>{score}</div>
                <div>{result}</div>
            </>
        )
    }
}

export default RSP

+ Recent posts