안 쓰던 블로그
React-컴포넌트 라이프사이클 메서드 본문
모든 리액트 컴포넌트에 존재하는 라이프 사이클
페이지에 렌더링되기 전 준비 과정에서 시작하여 페이지가 사라질 때 끝난다
마운트, 업데이트, 언마운트 총 세 가지 카테고리가 존재한다
마운트
DOM이 생성되고 웹 브라우저상에 나타나는 것: 마운트
마운트할 때 호출하는 메소드에는 네 가지가 있다
메소드 종류
constructor
컴포넌트를 새로 만들 때마다 호출되는 클래스 생성자 메서드
초기 state를 정할 수 있다
constructor(props){
super(props);
}
getDerivedStateFromProps
porps에 있는 값을 state에 동기화하는 메서드
리액트 v16.3부터 새로 생겼다
컴포넌트를 마운트하거나 props를 변경할 때 호출한다
static getDerivedStateFromProps(nextProps, prevState){
if(nextProps.value !== prevState.value){
return { color: nextProps.value };
}
return null;
}
render
프로그래머가 준비한 UI를 렌더링하는 메서드
라이프사이클 메서드 중 유일한 필수 메서드
이 메서드 안에서 this.props와 this.state에 접근할 수 있으며 리액트 요소를 반환한다
그 요소는 div요소 같은 태그가 될 수도 있고, 따로 선언한 컴포넌트일 수도 있고, null이나 false일수도 있다
이 안에서는 절대 state를 변형해서는 안 되고, 웹 브라우저에 접근해서도 안 된다
변화를 주고 싶다면 componentDisMount에서 처리한다
render() {...}
componentDisMount
컴포넌트가 웹 브라우저상에 나타난 후 호출되는 메서드
즉, 컴포넌트를 만들고 첫 렌더링을 다 마치면 호출된다
이 안에서 함수 호출, 이벤트 등록, setTimeout의 네트워크 요청 같은 비동기 작업도 한다
componentDidMount(){...}
호출 순서
constructor->getDerivedStateFromProps->render->componentDisMount
업데이트
컴포넌트를 업데이트하는 경우는 다음과 같습니다
-props가 바뀔 때
-state가 바뀔 때
-부모 컴포넌트가 리렌더링될 때
-this.forceUpdate로 강제 렌더링을 시도할 때
메소드 종류
getDerivedStateFromProps
마운트 과정에서도 호출하는 메서드인데, props가 바뀌어서 업데이트할 때도 쓴다
shouldComponentUpdate
props또는 state를 변경했을 때, 컴포넌트가 리렌더링을 해야 할지 말지를 결정하는 메서드
false면 아래 메서드들(render getSnap, DidUpdate) 스킵한다
컴포넌트를 만들 때 이 메서드를 따로 생성하지 않았다면 무조건 true를 리턴한다
이 메서드에서 this.porps와 this.state에 접근하고, 새로 설정될 nextProps나 nextState에도 접근할 수 있따
shouldComponentUpdate(nextProps, nextState){
console.log('shouldComponentUpdate', nextProps, nextState);
return nextState.number % 10 !==4;
}
render
컴포넌트 리렌더링
getSnapshotBeforeUpdate
컴포넌트 변화를 DOM에 반영하기 바로 직전에 호출하는 메서드
정확히는 render 메서드 호출 이후 DOM변화되기 직전에 실행된다
주로 업데이트하기 직전의 값을 참고할 일이 있을 때 활용한다(예: 스크롤바 위치 유지)
getSnapshotBeforeUpdate(prevProps, prevState){
console.log('getSnapshotBeforeUpdate');
if(prevProps.color !== this.prevState.color){
return this.myRef.style.color;
}
return null;
}
componentDidUpdate
컴포넌트의 업데이트 작업(리렌더링)이 끝나면 호출하는 메서드
업데이트가 끝났으니까 DOM관련 처리를 해도 괜찮다
prevProps나 provState를 사용해서 컴포넌트가 전에 가진 데이터에 접근할 수 있다
getSnapshotBeforeUpdate에서 반환한 값을 여기서 snapshot값으로 전달 받는다
componentDidUpdate(prevProps, prevState, snapshot){
console.log('componentDidUpdate', prevProps, prevState);
if(snapshot){
console.log('업데이트 되기 직전 색상: ', snapshot);
}
}
순서
1. props 변경이나 부모 리렌더링이 되면 getDerivedStateFromProps 호출
2. shouldComponentUpdate 호출. state를 변경했을 때는 이 메서드를 바로 호출
3. false면 여기서 종료. true면 4번으로
4. render 호출. forceUpdate를 한다면 이 메서드를 바로 호출
5. getSnapshotBeforeUpdate 호출
6. 웹 브라우저의 DOM 변화
7. componentDidUpdate 호출
언마운트
마운트의 반대 과정으로, 컴포넌트를 DOM에서 제거한다
메서드 종류
componentWillUnmount
컴포넌트가 웹 브라우저에서 사라지기 전에 호출하는 메서드
componentDidMount에서 등록한 이벤트, 타이머, 직접 생성 DOM이 있다면 여기서 제거한다
componentWillUnmount(){
console.log('componentWillUnmount');
}
순서
언마운트 실행->componentWillUnmount 호출
전체 코드
LifeCycleSample.js
import React, { Component } from 'react';
class LifeCycleSample extends Component {
state={
number: 0,
color: null
}
myRef=null; //ref설정
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('componentDidMounnt');
}
shouldComponentUpdate(nextProps, nextState){
console.log('shouldComponentUpdate', nextProps, nextState);
return nextState.number % 10 !== 4; //마지막 숫자 자리가 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;
이 컴포넌트는 각 라이프사이클 메서드를 실행할 때마다 콘솔 디버거에 기록,
부모 컴포넌트에서 props로 색상을 받아 버튼을 누르면 state.number값을 1씩 더한다
getDerivedStateProps가 부모에게서 받은 color값을 state에 동기화한다
getSnapshotBeforeUpdate는 DOM에 변화가 일어나기 직전의 색상 속성을 snapshot값으로 반환한다
이것을 componentDidUpdate에서 조회할 수 있다
shouldComponentUpdate에서 state.number값의 마지막 자릿수가 4면 리렌더링을 취소한다
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;
getRandomColor 함수가 state의 color값을 랜덤으로 설정한다
16777215는 hex로 ffffff이므로 000000~ffffff 중에 하나를 반환하는 식이다
버튼을 누를 때마다 getRandomColor를 가져와서 불러온 LifeCycleSample 컴포넌트에 color값으 props로 설정한다
처음 실행하면 마운트의 네 가지 메서드가 호출된다
랜덤 색성 버튼을 클릭하면 getDerived부터 업데이트 메서드들이 호출된다
더하기 버튼을 클릭해도 업데이트 메서드가 호출된다
componentDidUpdate의 값을 보면 그 전의 number값과 색상값이 담겨 있다
정리
참고한 책: 리액트를 다루는 기술-김민준 저 (http://www.yes24.com/Product/Goods/62597469)
'Web > React' 카테고리의 다른 글
React-컴포넌트 스타일링(CSS, Sass, styled-components) (0) | 2020.07.09 |
---|---|
React-함수형 컴포넌트 (0) | 2020.07.09 |
React-컴포넌트 반복(map()과 key) (0) | 2020.07.07 |
React-ref (DOM에 이름 달기) (0) | 2020.07.07 |
React-이벤트 핸들링(onChange, onClick, input 여러 개, onKeyPress) (0) | 2020.07.06 |