velopert님의 블로그에서 리액트 기초 과정을 보고 리액트를 알아가는 시간을 가졌으며,
해당 포스팅은 위 과정을 이해한대로 정리한 것이다.
(https://velopert.com/reactjs-tutorials)
LifeCycle API : 컴포넌트가 브라우저에서 나타날 때, 사라질 때, 업데이트 될 때 호출되는 API
컴포넌트가 브라우저에 나타나기 전, 후에 호출되는 API들은 아래와 같다.
컴포넌트의 업데이트는 props와 state의 변화에 따라 결정된다.
componentWillReceiveProps(nextProps){
}
컴포넌트가 새로운 props를 받게 됐을 때 호출, 주로 state가 props에 따라 변해야 하는 로직 작성
새로 받게될 props는 nextProps로 조회, 이 때 this.props는 업데이트 되기 전 API이다.
v16.3부터는 UNSAFE_componentWillReceiveProps()라는 이름으로 사용
static getDerivedStateFromProps(nextProps, prevState) {
// 여기서는 setState 를 하는 것이 아니라
// 특정 props 가 바뀔 때 설정하고 설정하고 싶은 state 값을 리턴하는 형태로
// 사용됩니다.
/*
if (nextProps.value !== prevState.value) {
return { value: nextProps.value };
}
return null; // null 을 리턴하면 따로 업데이트 할 것은 없다라는 의미
*/
}
shouldComponentUpdate(nextProps, nextState) {
// return false 하면 업데이트를 안함
// return this.props.checked !== nextProps.checked
return true;
}
조건에 따라 false를 반환하면 해당 조건에 render 함수를 호출(렌더링)하지 않는다.
componentWillUpdate(nextProps, nextState) {
}
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;
}
}
DOM 변화가 일어나기 직전의 DOM 상태를 가져오고, 리턴 값은 componentDidUpdate에서 3번째 파라미터로 받아올 수 있다.
componentDidUpdate(prevProps, prevState, snapshot) {
}
render()를 호출하고난 다음에 발생, 이 시점에서는 this.props와 this.state가 바뀐다.
파라미터를 통해 이전의 값인 prevProps와 prevState를 조회할 수 있다.
getSnapshotBeforeUpdate에서 반환한 snapshot값은 세번째 값으로 받아온다.
컴포넌트가 더 이상 필요하지 않을 경우, 호출되는 단 하나의 API
Counter.js를 아래와 같이 변경해보자.
class Counter extends Component {
state = {
number: 0
}
constructor(props) {
super(props);
console.log('constructor');
}
componentWillMount() {
console.log('componentWillMount (deprecated)');
}
componentDidMount() {
console.log('componentDidMount');
}
shouldComponentUpdate(nextProps, nextState) {
// 5 의 배수라면 리렌더링 하지 않음
console.log('shouldComponentUpdate');
if (nextState.number % 5 === 0) return false;
return true;
}
componentWillUpdate(nextProps, nextState) {
console.log('componentWillUpdate');
}
componentDidUpdate(prevProps, prevState) {
console.log('componentDidUpdate');
}
handleIncrease = () => {
const { number } = this.state;
this.setState({
number: number + 1
});
}
handleDecrease = () => {
this.setState(
({ number }) => ({
number: number - 1
})
);
}
render() {
console.log('render');
return (
<div>
<h1>카운터</h1>
<div>값: {this.state.number}</div>
<button onClick={this.handleIncrease}>+</button>
<button onClick={this.handleDecrease}>-</button>
</div>
);
}
}

console창을 통해 5의 배수일때 컴포넌트가 리렌더링 되지 않는 것을 확인 할 수 있다.