라이프사이클 메서드의 종류는 총 9가지
DOM이 생성되고 웹 브라우저상에 나타나는 것.
마운트할 때는 다음의 메서드들이 차례대로 호출된다.
컴포넌트는 다음의 경우에 업데이트를 한다.
1, 2, 3이 발생하면 다음과 같은 순서로 메서드가 호출된다.
컴포넌트를 DOM에서 제거하는 것.
render() {...}
constructor(props) {...}
componentDidMount() {...}
shouldComponentUpdate(nextProps, nextState) {...}
//스크롤바 위치 유지를 위해 업데이트 직전 값 참고 getSnapshotBeforeUpdate(prevProps, prevState){ if(prevState.array !== this.state.array){ const { scrollTop, scrollHeight } = this.list; return { scrollTop, scrollHeight }; } }
componentDidUpdate(prevProps, prevState, snapshot) {...}
componentWillUnmout(){...}
- 컴포넌트를 DOM에서 제거할 때 실행
- componentDidMount에서 등록한 이벤트, 타이머, 직접 생성한 DOM은 여기서 제거작업을 해야 함.
componentDidCatch(error, info){ this.setState({ error: true }); console.log({error, info}); }
LifeCycleSample 컴포넌트 만들기 -> App에 렌더링하기 -> 버튼 누르고 콘솔 창 관찰하기
전체 코드
//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;
import React, { 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("componenetDidMount");
}
shouldComponentUpdate(nextProps, nextState) {
console.log("shouldComponentUpdate", nextProps, nextState);
//숫자의 마지막 자리가 4면 리렌더링 하지 않습니다
return nextState.number % 10 !== 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>
{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>
);
}
}
export default LifeCycleSample;
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;
정리