November 09, 2019
리액트 컴포넌트는 수명 주기란 것이 존재한다. 그리고 수명 주기는 크게 세 가지로 분류됨.
constructor -> getDerivedStateFromProps -> render -> componentDidMount컴포넌트를 만들 때, 가장 처음으로 실행되는 생성자 메소드. state의 기본값을 이 곳에서 설정함.
props로 받아온 값을 state에 동기화 시킴. 마운트 혹은 업데이트 시 호출.
컴포넌트 정의 메소드. 리액트의 필수 메소드임. render 메소드는 요소를 반환하는 역할을 하기에, state를 변경하거나, DOM에 접근은 불가하다(하면 안됨)
화면 렌더링이 끝나면 호출되는 메소드. 페이지에 마운트가 끝난 후 실행하기 때문에, 다른 JS 라이브러리를 호출하거나, 혹은 이벤트를 등록하거나, 비동기 작업 등을 처리할 때 사용한다.
getDerivedStateFromProps -> shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdateprops나 state 값이 변경될 때, 새로 렌더링을 할 지 말 지 결정하는 메소드. 반드시 true 혹은 false 값을 반환 해야함. 성능을 위해 컴포넌트를 최적화시킬 경우, 리렌더링 방지를 위해 사용하게 될 것!
언제나 기본값은 true 상황에 따라 false를 반환하도록 해야한다.
현재 props나 state는 this.props or state로 접근, 새로 설정될 값은 next.props or state로 접근하면 된다.
render 메소드 다음, DOM을 변경하기 바로 직전에 호출되는 메소드. 업데이트하기 직전 값을 참고해야할 일이 있을 때 활용됨.
ex) 스크롤바 위치 유지
반환값은 componentDidUpdate의 파라미터인 snapshot으로 전달.
리렌더링(업데이트)를 마친 후 실행. componentDidMount메소드처럼 DOM 처리가 가능하다. 해당 메소드에서는 변경 직전의 state와 props의 데이터에 접근할 수 있음.
componentWillUnMount컴포넌트를 제거할 때 실행. componentDidMount에서 등록했던 이벤트나 타이머 혹은 직접 생성한 DOM을 제거해야함.
LifeCycle.js :
import React, { Component } from 'react'
class LifeCycleSample extends Component {
state = {
number: 0,
color: null,
}
// ref를 설정
// 직접 DOM에 접근할 경우, ref를 이용한다.
myRef = null
// 1. 첫번째로 호출되는 메소드
constructor(props) {
super(props)
console.log('constructor')
}
// 2. 받아온 props를 state에 동기화
// 만약 다음에 받아올 color값이 변한다면 다음 color값으로 return
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.color !== prevState.color) {
return { color: nextProps.color }
console.log('getDerivedStateFromProps')
}
console.log('no!!!!')
// 반환값이 없다면 return 값은 null
return null
}
componentDidMount() {
console.log('componentDidMount')
}
// 4. 리렌더링 할 지 말 지 결정. 리턴값은 boolean
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate', nextProps, nextState)
// 리턴값이 4가 아니라면 true, 4라면 false
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>
<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 LifeCycleSampleApp.js :
import React, { Component } from 'react'
import LifeCycleSample from './LifeCycleSample'
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>
<LifeCycleSample color={this.state.color} />
</div>
)
}
}
export default App