모든 컴포넌트의 수명은 렌더링 되기 전인 준비 과정 ~ 페이지에서 사라질 때 까지이다. lifecycle method는 class형 컴포넌트에서만 사용할 수 있고 함수형 컴포넌트에서는 hook을 사용한다.
lifecycle method 종류
- will 접두사가 붙은 메서드 : 어떤 작업을 작동하기 전에 실행
- did 접두사가 붙은 메서드 : 어떤 작업을 작동한 후에 실행
lifecycle
- mount : 페이지에 컴포넌트가 나타남, DOM이 생성되고 웹에 나타난다
constructor : 컴포넌트를 새로 만들때마다 호출되는 클래스 생성자 메서드
getDerivedStateFromProps : props에 있는 값을 state에 넣을 때 사용하는 메서드
render : 우리가 준비한 UI를 렌더링
componentDidMount : 컴포넌트가 웹 브라우저상에 나타난 후 호출하는 메서드
- update : 리렌더링을 통해 컴포넌트 정보가 업데이트 됨
props 변경, state 변경, 부모 컴포넌트가 리렌더링, this.forceUpdate로 강제로 렌더링을 트리거할 때 update 발생
getDerivedStateFromProps : 마운트 과정에서도 호출되며 업데이트 시작 전ㄴ에도 호출된다. props의 변화에 따라 state에도 변화를 주고 싶을 때 사용
shouldComponentUpdate : 컴포넌트가 리렌더링을 해야 할지 말아야할지를 결정하는 메서드. true/false를 반환하는데 true는 다음 라이프사이클 메서드 계속 실행, false는 작업을 중지하여 리렌더링을 하지 않음
render : 컴포넌트 리렌더링
getSnapshotBeforeUpdate : 컴포넌트 변화를 DOM에 반영하기 바로 직전에 호출하는 메서드
componentDidUpdate : 컴포넌트의 업데이트 작업이 끝난 후 호출
- unmount : 페이지에서 컴포넌트가 사라짐
componentWillUnmount : 컴포넌트가 웹 브라우저 상에서 사라지기 전에 호출
예제
- LifeCycleSample.js
import {Component} from 'react';
class LifeCycleSample extends Component{
state = {
number: 0,
color:null,
}
myRef = 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){
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;
- App.js
import { Component } from 'react';
import './App.css';
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;
App(parent component)에서 글자의 색상을 바꾸는 버튼, LifeCycleSample(child component)에서 숫자를 더하는 버튼을 배치하였다. 가장 최초에 렌더링 되는 순서는 다음과 같다. console창에서 확인할 수 있다.
이 때, 더하기 버튼을 클릭하면 다음과 같은 순서로 업데이트가 일어난다.
랜덤 색상 버튼을 클릭하면 다음과 같은 순서로 업데이트가 일어난다.
getDerivedStateFromProps는 parent에서 받은 color값을 state에 동기화 하고, DOM에 변화가 일어나기 직전의 색상을 snaphot값으로 반환하여 componentDidUpdate에서 조회할 수 있게 하였다.
Error 사용자에게 알려주기
만약 LifeCycleSample.js 의 render함수에 다음이 포함되어있다고 할 때 value를 알 수 없으므로 Error가 발생하는데 화면에는 아무것도 나오지 않게 된다.
render() {
console.log('render');
const style = {
color : this.props.color
};
return(
<div>
{this.props.missing.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>
)
};
따라서 사용자가 에러가 발생했음을 알 수 있도록 ErrorBoundary 컴포넌트를 생성해보자.
에러가 발생하면 componentDidCatch 메서드가 호출되며 this.state.error 값을 true로 업데ㅔ이트 한다.
-ErrorBoundary.js
import React, { Component } from 'react';
class ErrorBoundary extends Component {
state = {
error: false
};
componentDidCatch(error, info) {
this.setState({
error: true
});
console.log({ error, info });
}
render() {
if (this.state.error) return <div>에러가 발생했습니다!</div>;
return this.props.children;
}
}
export default ErrorBoundary;
- App.js
import { Component } from 'react';
import './App.css';
import ErrorBoundary from './ErrorBoundary'
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>
<ErrorBoundary>
<LifeCycleSample color = {this.state.color}/>
</ErrorBoundary>
</div>
);
}
}
export default App;
'Programming > React.js' 카테고리의 다른 글
8. Component styling (0) | 2022.03.08 |
---|---|
7. Hooks (0) | 2022.03.06 |
5. 반복적으로 Component 사용하기 (0) | 2022.03.05 |
4. ref:DOM에 이름 달기 (0) | 2022.03.05 |
3. 이벤트 핸들링 (0) | 2022.03.05 |