constructor()
constructor(props) {
super(props);
}
componentDidMount()
componentDidMount() {
// 외부 라이브러리 연동: D3, masonry, etc
// 컴포넌트에서 필요한 데이터 요청: Ajax, GraphQL, etc
// DOM 에 관련된 작업: 스크롤 설정, 크기 읽어오기 등
}
static getDerivedStateFromProps()
static getDerivedStateFromProps(nextProps, prevState) {
// 여기서는 setState 를 하는 것이 아니라
// 특정 props 가 바뀔 때 설정하고 설정하고 싶은 state 값을 리턴하는 형태로
// 사용됩니다.
if (nextProps.value !== prevState.value) {
return { value: nextProps.value };
}
return null; // null 을 리턴하면 따로 업데이트 할 것은 없다라는 의미
}
shouldComponentUpdate()
shouldComponentUpdate(nextProps, nextState) {
if (nextState.number % 5 === 0) return false;//업데이트를 안함
return true;
}
}
//이 함수는 기본적으로는 true를 반환!
componentWillUpdate
componentWillUpdate(nextProps, nextState) {
}
//이 다음에 render()
getSnapshotBeforeUpdate()
getSnapshotBeforeUpdate(prevProps, prevState) {
// DOM 업데이트가 일어나기 직전의 시점입니다.
// 새 데이터가 상단에 추가되어도 스크롤바를 유지해보겠습니다.
// scrollHeight 는 전 후를 비교해서 스크롤 위치를 설정하기 위함이고,
// scrollTop 은, 이 기능이 크롬에 이미 구현이 되어있는데,
// 이미 구현이 되어있다면 처리하지 않도록 하기 위함입니다.
if (prevState.array !== this.state.array) {
const {
scrollTop, scrollHeight
} = this.list;
// 여기서 반환 하는 값은 componentDidMount 에서 snapshot 값으로 받아올 수 있습니다.
return {
scrollTop, scrollHeight
};
}
}
이 API 가 발생하는 시점 확인!
componentDidUpdate()
componentDidUpdate(prevProps, prevState, snapshot) { }
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot) {
const { scrollTop } = this.list;
if (scrollTop !== snapshot.scrollTop) return; // 기능이 이미 구현되어있다면 처리하지 않습니다.
const diff = this.list.scrollHeight - snapshot.scrollHeight;
this.list.scrollTop += diff;
}
}
전체 코드
import React, { Component } from "react";
import "./ScrollBox.css";
class ScrollBox extends Component {
id = 2;
state = {
array: [1]
};
handleInsert = () => {
this.setState({
array: [this.id++, ...this.state.array]
});
};
getSnapshotBeforeUpdate(prevProps, prevState) {
// DOM 업데이트가 일어나기 직전의 시점입니다.
// 새 데이터가 상단에 추가되어도 스크롤바를 유지해보겠습니다.
// scrollHeight 는 전 후를 비교해서 스크롤 위치를 설정하기 위함이고,
// scrollTop 은, 이 기능이 크롬에 이미 구현이 되어있는데,
// 이미 구현이 되어있다면 처리하지 않도록 하기 위함입니다.
if (prevState.array !== this.state.array) {
const { scrollTop, scrollHeight } = this.list;
// 여기서 반환 하는 값은 componentDidMount 에서 snapshot 값으로 받아올 수 있습니다.
return {
scrollTop,
scrollHeight
};
}
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot) {
const { scrollTop } = this.list;
if (scrollTop !== snapshot.scrollTop) return; // 기능이 이미 구현되어있다면 처리하지 않습니다.
const diff = this.list.scrollHeight - snapshot.scrollHeight;
this.list.scrollTop += diff;
}
}
render() {
const rows = this.state.array.map(number => (
<div className="row" key={number}>
{number}
</div>
));
return (
<div>
<div
ref={ref => {
this.list = ref;
}}
className="list"
>
{rows}
</div>
<button onClick={this.handleInsert}>Click Me</button>
</div>
);
}
}
export default ScrollBox;
컴포넌트가 더 이상 필요하지 않게 되면 단 하나의 API 가 호출
componentWillUnmount()
componentWillUnmount() {
// 이벤트, setTimeout, 외부 라이브러리 인스턴스 제거
}
componentDidCatch
componentDidCatch(error, info) {
this.setState({
error: true
});
}
import React, { Component } from 'react';
const Promblematic = () => {
throw (new Error('버그가 나타났다!'));
return (
<div>
</div>
);
};
class Counter extends Component {
state = {
number: 0,
error: false
}
// (...)
componentDidCatch(error, info) {
this.setState({
error: true
});
}
render() {
if (this.state.error) return (<h1>에러발생!</h1>);
return (
<div>
<h1>카운터</h1>
<div>값: {this.state.number}</div>
{ this.state.number === 4 && <Promblematic /> }
<button onClick={this.handleIncrease}>+</button>
<button onClick={this.handleDecrease}>-</button>
</div>
);
}
}
export default Counter;
주로 언제 쓰이는지까지 같이 있어서 이해가 더 잘 돼요👍👍👍👍👍