😀 라이프사이클 메서드의 이해
- 컴포넌트를 처음 렌더링 할 떄, 작업을 처리해야 할 때
- 컴포넌트를 업데이트 하기 전후로 어떤 작업을 처리해야 할 때
- 라이프사이클은 클래스형 컴포넌트에서만 사용할 수 있다.
- 함수형 컴포넌트에서는 Hooks를 사용한다.
- Will 접두사가 붙은 것은 어떤 작업을 하기 전에 실행되는 메서드
- Did 접두사가 붙은 것은 어떤 작업을 한 이후에 실행되는 메서드
- 라이프 사이클은 총 세 가지, 즉 마운트, 업데이트, 언마운트 카테고리로 나뉜다.
마운트
- constructor: 컴포넌트를 새로 만들 때마다 호출되는 클래스 생성자 메서드
- getDerivedStateFromProps: props에 있는 값을 state에 넣을 때 사용하는 메서드
- render: 우리가 준비한 UI를 렌더링하는 메서드
- componentDidMount: 컴포넌트가 웹 브라우저상에 나타난 후 호출하는 메서드
업데이트
- 컴포넌트가 업데이트 되는 경우
- props가 바뀔 때
- state가 바뀔 때
- 부모 컴포넌트가 리렌더링 될 때
- this.forceUpdate로 강제로 렌더링을 트리거할 때
- getDerivedStateFromProps: (생략)
- shouldComponentUpdate:
- 렌더링 할 지 말 지를 결정하는 메서드.
- boolean을 반환해야 하며 true를 반환하면 새로 렌더링 한다.
- 만약 this.forceUpdate() 함수를 호출한다면 이 과정은 생략되고 바로 render 함수를 호출한다.
- render: (생략)
- getSnapshotBeforeUpdate:
- 컴포넌트 변화를 DOM에 반영하기 직전에 호출되는 메서드이다.
- 주로 스크롤바 위치 유지와 같은 용도로 쓴다.
- componentDidUpdate: (생략)
언마운트
- componentWillUnmount: (생략)
componentDidCatch
- 렌더링 도중 에러가 발생하면 오류 UI를 보여줄 수 있게 한다.
🙄 라이프사이클 메서드 사용하기
import React, { Component } from "react";
export default 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 % 2 !== 1;
}
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("just before updating", 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}>plus</button>
</div>
);
}
}
import React, { Component } from "react";
import LifeCycleSample from "./LifeCycleSample";
import ErrorBoundary from "./ErrorBoundary";
function getRandomColor() {
return "#" + Math.floor(Math.random() * 16777215).toString(16);
}
export default class App extends Component {
state = {
color: "#000000"
};
handleClick = () => {
this.setState({
color: getRandomColor()
});
};
render() {
return (
<div className="App">
<button onClick={this.handleClick}>random color</button>
<ErrorBoundary>
<LifeCycleSample color={this.state.color} />
</ErrorBoundary>
</div>
);
}
}
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>error occur</div>;
return this.props.children;
}
}
export default ErrorBoundary;