[React] Component Lifecycle

홍인열·2022년 2월 15일
0
post-thumbnail
post-custom-banner

최근 프로젝트를 진행하다보니 불필요한 Render가 발생하는데 이를 해결하지 못한 경우가 많았다. 그래서 lifecycle에 대한 이해를하고 랜더링을 최적화 시키고자한다. 그전에 lifecycle은 리액트 버전 16.3 이후 봐낀부분이 있다고한다 (CampBu 개발시 리액트 버전 17.0.2). 봐낀부분을 쉽게 이해하려면 봐끼기 전부터 알아야하니 이저 lifecycle부터 이해해보자.

리액트 버전 16.3 이하

Component Lifecycle

리액트 컴포넌트가 생성되고 사라질때까지 여러지점에서 개발자가 작업이 가능하도록 메서드를 통해 코드 실행 순서를 지정할 수 있게 해준다.

Declarative 디클레러티브

What is Declarative ?
✔️ 리액트 컴포넌트 라이프사이클은 디클레러티브라는 성질을 가지고 있다. 의미는 선언적 랜더링 방식으로 컴포넌트의 생명주기에 각 지점을 선언적으로 표현해 놓으면 해당지점에서 코드가 실행되도록 하는 방식.

Initialization

  • setup props and state (constructor)
    : 맨처음 props를 불러오고 state 초기값이 설정되는 부분.

Mounting

✔️ Mounting까지가 초기에 브라우저에 그려지는 부분.

  • componentWillMount
    : 브라우저에 보여지기 직전 즉, render가 되기 직전에 호출.
  • render
  • componentDidMount
    : 브라우저에 보여진 후 즉, render가 되기 직후 호출.

class App extends React.Component {
  state = {
    message : 'hello'
  }
  constructor(props) {
    super(props);
    console.log('첫번째 로그')
  }
  
  render() {
    console.log('세번째 로그')
    return <div>{this.state.mesage}</div>
  }
  
  componentWillMount() {
    console.log('두번재 로그')
  }
  componentDidMount() {
  	console.log('네번째 로그')
  }
}

// App 컴포넌트가 실행되고 콘솔로그를 확인하면
// constructor - componentWillMount - render - componentDidMount 순서로 실행됨을 확인 할 수 있다.

Updation

📌 props나 state가 변경되면 render 메서드가 다시 실행된다.

propsstate
• componentWillReceivePropsprops를 새로 지정하면 바로 호출됨.
state 변경에 반응하지않음.
props값에 따라 state 변경 필요시 setState를 사용.
➔ 다음 이벤트로 각각 가지않고 한번에 변경해서
shouldComponentUpdate로 보냄.
• shouldComponentUpdate• shouldComponentUpdateprops, state중 하나만 변경되어도 호출.
변경된 props와 변경된 state를 인자로 받음.
return type은 boolean이며, true면 render,
false면 render 미호출.
해당함수 미구현시 default는 true.
• componentWillUpdate• componentWillUpdate컴포넌트가 재랜더링 되기 직전에 호출
setState등을 사용하면 안됨.
• render• render-
• componentDidUpdate• componentDidUpdate컴포넌트가 재랜더링 된 직후에 호출
해당 컴포넌트가 사용하던 메모리등을 정리하는데 사용.

class App extends React.Component {
  state = {
    message : 'hello'
  }
  constructor(props) {
    super(props);
    console.log('첫번째 로그')
  }
  
  render() {
    console.log('세번째 로그')
    return <div>{this.state.mesage}</div>
  }
  
  componentWillMount() {
    console.log('두번재 로그')
  }
  componentDidMount() {
  	console.log('네번째 로그')
  }

  // 최초 렌더링 이후에는 props나 state가 변경되면 재랜더링이 일어나게된다.
  componentWillReceiveProps(nextProps){ //변경된 props를 인자로 받는다.
    console.log('프롭스가 변경될경우만 맨처음 실행')
  }
  shouldComponentUpdate(nextProps, nextState) { //변경된 props와 state를 인자로 받는다.
   console.log('return(boolean)에 따라 랜더가 진행될지 말지가 결정된다')
   return true // true가 재랜더가 진행된다.
  }

  componentWillUpdate(nextProps, nextState) {
    console.log('재 랜더가 실행되기 직전')
  }
  componentDidUpdatep(prevProps, prevState {//랜더된 후 이기 때문에 prevProps, prevState를 인자로 받는다.
    console.log('재랜더 직후 실행되는 함수')
  }
                    
}

Unmounting

  • componentWillUnmout
    : 해당 컴포넌트가 사라지기 직전 호출
//class component 내에
//setInterval과 같이 전역상태로 실행중인 함수들을 초기화 할 수 있다.

interval = setInterval(()=>{console.log('tiktok')},1000)

componentWillUnmout(){
	clearInterval(this.interval)
}

리액트 버전 16.3

component Lifecycle을 초기 - 업데이트 - 사라짐으로 나눠본다면 다음과 같이 변경되었다.
각 지점에서 실행되는 함수 일부가 변경되었고 파라미터 및 리턴 결과가 봐끼었다.

초기

construct
componentWillMount ➔ getDerivedStateFromProps
render
componentDidMount

//새로운 props와 이전state를 인자로 받는다.

state = {
  message:'hello'
}
...
getDerivedStateFromProps(nextProps,prevState){
  //반환값으로 새로운 state.
  return {
   message:'hi'
  }
}

업데이트

componentWillReceiveProps ➔ getDerivedStateFromProps
shouldComponentUndate
render
componentWillUpdate ➔ getSnapshotBeforeUpdate
(dom에 적용)
componentDidMount

getSnapshotBeforeUpdate(prevProps, prevState) {
  ...
  return value// 반환되는 값은 snapshot으로 저장.
}

// conponetDidMount의 3번째 인자로 snapshot을 받게된다.
componentDidMount(prevProps, prevState, snapshot){
 ...
}
  

사라짐

componentWillUnmount

componentDidCatch

해당 컴포넌트의 하위 컴포넌트에서 에러가날 경우 호출되는 함수.
에러발생시 상태를 변경하여 다른 코드를 보여줄수 있도록 할 수 있음.

class App extends React.component {
  state = {
    hasError: false,
  };
  render () {
    ...
  }
  componentDidCatch(error, info){
   this.setState({hasError : true});
  }
}
profile
함께 일하고싶은 개발자
post-custom-banner

0개의 댓글