이번 7장에서는 컴포넌트의 라이프사이클 메서드에 대해서 알아보고자 합니다.
모든 리액트 컴포넌트에는 라이프사이클-수명 주기-가 존재하는데,
이는 컴포넌트 상태의 변화가 있을 때부터 실행하는 함수로서,
컴포넌트의 수명은 페이지 렌더링 전부터, 페이지의 삭제까지입니다.
그런데, 리엑트 프로젝트를 진행하다 보면, 이러한 컴포넌트의 수명주기에 개입해 조작해야 하는 경우가 생길 수 있습니다. 가령 컴포넌트의 업데이트 전후에 추가 작업 처리를 만들거나, 특정 업데이트를 방지하는 경우처럼요.
이러한 상황을 위해, 컴포넌트의 라이프사이클 메서드가 이용됩니다.
라이프사이클 메서드의 특징 중 하나는, 함수형 컴포넌트에는 사용 불가능하고, 클래스형 컴포넌트에서만 사용할 수 있다는 점입니다.
라이프사이클 메서드는 총 9개의 종류가 있습니다.
그중, 접두사 두 가지의 특징은 아래와 같습니다.
라이프사이클은 총 세가지 카테고리로 나눌 수 있습니다.
|
마운트
|
업데이트
|
언마운트
|
||
정의
|
DOM이 생성되고 웹 브라우저 상에 나타나는 것
|
props/state의 변화, 혹은 부모 컴포넌트의 리렌더링, 또는 this.forceUpdate로 인한 강제 리렌더링 시 업데이트가 일어남
|
마운트의 반대과정이다. 컴포넌트를 DOM에서 제거하는 것
|
||
호출 메서드 도식화
|
아래의 매서드를 순서대로 실행한다
|
||||
메서드
|
constructor
|
getDerivedStateFromProps
|
componentWillUnmount
|
||
getDerivedStateFromProps
|
shouldComponentUpdate
|
|
|||
render
|
render
|
|
|||
componentDidMount
|
getSnapshotBeforeUpdate
|
|
|||
|
componentDidUpdate
|
|
static getDerivedStateFromProps(nextProps, prevState) {
if(nextProps.value != = prevState.value) { // 조건에 따라 특정 값 동기화
return { value: nextProps.value };
}
return null; // state를 변경할 필요가 없다면 null을 반환
}
static getSnapshotBeforeUpdate(prevProps, prevState) {
if(prevProps.array != = this.state.arrray) { // 조건에 따라 특정 값 동기화
const { scrollTop, scrollHeight } = this.list
return { scrollTop, scrollHeight };
}
}
componentDidCatch(error, info) { //error = 파라미터에게 발생 에러 알려줌. info = 코드 위치 알려줌
this.setState({
error: true
});
console.log({error, info });
}
src 디렉터리에 LifeCycleSample 이라는 컴포넌트를 생성하면, 아래와 같습니다.
// LifeCycleSample.js
import { Component } from 'react1;
class LifeCycleSample extends Component {
state = {
number: 0,
color: null,
}
myRef = null; // ref를 설정할 부분
constructor(props) {
super(props);
console.log( constructor');
}
static getDerivedStateFromProps(nextProps, prevState) {
// getDerivedStateFromProps ; 부모에게 받은 color를 state에 동기화
console.log('getDeriv은dStateFromProps');
if(nextProps.color !== prevState.color) {
return { color: nextProps.color };
}
return null;
}
componentDidMount() {
console.log('componentDidMount*);
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate', nextProps, nextState);
// shouldComponentUpdate : 숫자의 마지막 자리가 4면 리렌더링하지 않습니다. 4, 14, 24,,,
return nextState.number % 10 !== 4;
}
componentWillUnmo니nt() {
console.log(,componentWillUnmount,);
}
handleClick =()=>{
this.setState({
number: this.state.number + 1
});
}
getSnapshotBeforeUpdate(prevPropsz prevState) { //DOM 변화 일어나기 직전 색상 속성을 snapshot으로 반환
console.log('getSnapshotBeforeUpdate');
if(prevProps.color !== this.props.color) {
return this.myRef.style.color;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) { // 반환값 조회
console.log(*componentDidUpdate1z 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;
위의 코드는, 콘솔 디버거에 라이프사이클 메서드의 실행 결과를 기록한다는 점과
버튼을 누르면 state.number 값을 1씩 더한다는 특징이 있습니다.
보다 자세한 내용은 코드 내 주석 참고를 바랍니다.
다음으로, 기존의 app.js 파일을 아래와 같이 수정하면 다음과 같습니다.
// app.js
import { Component } from 'react';
import LifeCycleSample from ./LifeCycleSample';
function getRandomColor() {
// getRandomColor : state의 color 값을 랜덤으로 생성. hex(000000~ffffff)
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;
이는 버튼을 클릭하면, 랜덤 색상을 보여주는 코드를 의미합니다.
위와 같은 코드에서는 어떨 때 에러가 발생할까요?
대체로, 존재하지 않는 함수를 사용하려는 시도-호출이나,
존재하지 않는 - 선언되지 않은 객체 값을 조회하려 할 때.
이 두 가지 경우입니다.
후자의 사례를 관찰하기 위해, render() 함수에 대해서 아래와 같은 코드를 <div> 사이에 작성해봅시다.
{this.props.missing.value}
이와 같은 잘못된 코드를 실행하면, 존재하지 않는 missing 객체의 value를 조회하려 하기에,
undefined 에러가 실행되고, 또는 빈 페이지를 브라우저 탭에서 볼 수 있을 것입니다.
에러 페이지가 나올 때, 이 페이지가 에러임을 나타내 주는 페이지를 아래와 같은 코드로 작성해볼 수 있습니다.
//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;
이렇게 작성한 ErrorBoundary.js 코드를 반영하기 위해서 App.js 코드를 아래와 같이 수정할 수 있습니다.
//App.js
import React, { Component } from 'react';
import Lifecyclesample from './Lifecyclesample';
import ErrorBoundary from './ErrorBoundary';
// 랜덤 색상을 생성합니다.
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;
위에서 설명한 바와 같이, 컴포넌트 라이프사이클은 3개의 단계로 나눌 수 있습니다.
마운트, 업데이트, 언마운트입니다.
위의 코드들을 정리해, 메서드의 흐름을 도식화한다면 아래의 사진과 같습니다.
* 퀴즈!~!
|
문제
|
답
|
1
|
컴포넌트 상태에 변화가 있을 때마다 실행하는 메서드는?
|
라이프사이클 메서드
|
2
|
컴포넌트 라이프사이클을 크게 3개로 분류하면?
|
마운트, 업데이트, 언마운트
|
3
|
shouldComponentUpdate의 특징을 말한다면?
|
컴포넌트의 업데이트 성능을 개선할 때 중요하게 쓰인다
|
4
|
존재하지 않는 함수를 호출할 때 발생하는 상황은?
|
에러, 오류
|
5
|
존재하지 않는 컴포넌트의 객체를 부를 때 발생하는 상황은?
|
에러, 오류
|
6
|
에러가 발생할 때, 사용자에게 보여줄 파일을 작성한다면, 이를 기존의 App.js파일에 연결하는 방법은 무엇일까? (코드 작성)
|
import문을 이용해 작성한 js파일을 호출한다.
태그를 이용해 render() 함수에서 이를 부른다.
등
|
7
|
라이프사이클 메서드에서 유일한 필수 메서드는 무엇일까?
|
render()
|
8
|
마운트를 설명한다면?
|
DOM이 생성되고 웹 브라우저 상에 나타나는 것
|
9
|
업데이트를 간략히 설명한다면?
|
props/state의 변화, 혹은 부모 컴포넌트의 리렌더링, 또는 this.forceUpdate로 인한 강제 리렌더링 시 업데이트가 일어남
|
10
|
언마운트를 설명한다면?
|
마운트의 반대과정이다. 컴포넌트를 DOM에서 제거하는 것
|
Corner React1
Editor: 라마
[리액트 스타터1] 9장. 컴포넌트 스타일링 (0) | 2022.12.01 |
---|---|
[리엑트 스타터1] 8장. Hooks (0) | 2022.11.24 |
[리액트 스타터1] 6장. 컴포넌트 반복 (0) | 2022.11.10 |
[리액트 스타터 1] 5장. ref (0) | 2022.11.05 |
[리액트 스타터1] 4장. 이벤트 핸들링 (0) | 2022.10.13 |