[React] 9. 라이프사이클 메서드
1. 라이프사이클 메서드 정리 ✍
1.1 render() 함수
render() {...}
- 라이프사이클 메서드 중 유일한 필수 메서드이다.
- 이 메서드 안에서
this.props
와 this.state
에 접근할 수 있으며, 리액트 요소를 반환한다.
예를 들어, div 태그
, 컴포넌트
등
render() {...}
this.props
와 this.state
에 접근할 수 있으며, 리액트 요소를 반환한다.예를 들어,
div 태그
, 컴포넌트
등주의할점❗❗
- 이벤트 설정이 아닌 곳에서
setState
를 사용하면 안되고, 브라우저의DOM
에 접근해도 안된다.
DOM 정보를 가져오거나state
에 변화를 줄 때는componentDidMount
에서 처리해야 한다.
1.2 constructor 메서드
constructor(props) {...}
- 컴포넌트의 생성자 메서드로 컴포넌트를 만들 때 처음으로 실행되고, 초기
state
를 정할 수 있다.
1.3 getDerivedStateFromProps 메서드
- 리액트 v16.3 이후에 만들어진 메서드로,
props
로 받아 온 값을state
에 동기화시키는 용도로 사용하고 컴포넌트가 마운트될 때와 업데이트될 때 호출된다.
static getDerivedStateFromProps(nextProps, prevState) {
if(nextProps.value !== prevState.value) { // 조건에 따라 특정 값 동기화
return { value: nextProps.value };
}
return null; // state를 변경할 필요가 없다면 null 반환
}
1.4 componentDidMount 메서드
componentDidMount() {...}
- 컴포넌트를 만들고, 첫 렌더링을 마친 후 실행하는 메서드이다.
- 이 메서드를 통해 다른
자바스크립트 라이브러리
또는프레임워크의 함수를 호출
,이벤트 등록
,setTimeout
,setInterval
,네트워크 요청
같은 비동기 작업 처리한다.
1.5 shouldComponentUpdate 메서드
shouldComponentUpdate(nextProps, nextState) {...}
props
orstate
를 변경했을 때, 리렌더링을 시작할지 여부를 지정하는 메서드이다.- 위의 언급대로
true
,false
반환하며, 컴포넌트를 만들 때 이 메서드를 따로 사용하지 않으면 기본값은true
를 반환한다.❗❗ - 현재
props
와state
는this.props
와this.state
로 접근하고, 새로 설정될props
와state
는nextProps
,nextState
로 접근한다.
TIP ❗❗
프로젝트 성능을 최적화할 때, 상황에 맞는 알고리즘을 사용하여 리렌더링을 방지할 때는false
값을 반환하면 된다.
1.6 getSnapshotBeforeUpdate 메서드
- 리액트 v16.3 이후 만들어진 메서드로
render
에서 만들어진 결과물이 브라우저에 실제로 반영되기 직전에 호출된다. - 이 메서드에서 반환하는 값은
componentDidUpdate
에서 세 번째파라미터
인snapshot
값으로 전달받으며, 주로 업데이트하기 직전의 값을 참고할 때 사용한다.
👉 (ex. 스크롤바 위치 유지)
getSnapshotBeforeUpdate(prevProps, prevState) {
if(prevState.array !== this.state.array) {
const { scrollTop, scrollHeight } = this.list
return { scrollTop, scrollHeight };
}
}
1.7 componentDidUpdate 메서드
componentDidUpdate(prevProps, prevState, snapshot) {...}
- 리렌더링을 완료 후 실행하는 메서드로,
업데이트
가 끝난 직후라서DOM
관련 처리를 해도 상관없다. - 여기서
prevProps
orprevState
를 사용해서 컴포넌트가 이전에 가졌던 데이터에 접근할 수 있다. - snapshot 값은
getSnapshotBeforeUpdate
에서 반환한 값으로 전달받을 수 있다.
1.8 componentWillUnmount 메서드
componentWillUnmount() {...}
- 컴포넌트를 DOM에서 제거할 때 사용한다.
componentDidMount
에서 등록한이벤트
,타이머
,직접 생성한 DOM
이 있다면 여기서 제거해야 한다.
1.9 componentDidCatch 메서드
- 리액트 v16에 새롭게 생성된 메서드로, 컴포넌트 렌더링 도중에 에러가 발생했을 때
오류 UI
를 보여 줄 수 있다.
componentDidCatch(error, info) {
this.setState({
error: true
});
consol.log({ error, info });
}
error
는 파라미터에 어떤 에러가 발생했는지 알려주고,info
는 어디에 있는 코드에서 오류가 발생했는지에 대한 정보를 담고있다.
알고 넘어가기 ❗❗
- 이 메서드는 컴포넌트 자신에게 발생하는 에러는 잡을 수 없고 자신의
this.props.children
으로 전달되는 컴포넌트에서 발생하는 에러만 잡을 수 있다.
2. 라이프사이클 메서드 실습
2.1 컴포넌트 생성
src/LifeCycleSample.js
를 생성하여 아래와 같이 코드를 작성했다.
//LifeCycleSample.js
class LifeCycleSample extends Component {
state = {
number: 0,
corlor: null,
}
myRef = null; // ref를 설정할 부분
constructor(props) {
super(props);
console.log('constructor');
}
static getDerivedStateFormProps(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);
// 숫자 마지막 자리가 4면 리렌더링 안함.
return nextState.number % 10 !== 4;
}
componentWillUnmount() {
console.log('componentWillUnmount');
}
handleClick = () => {
this.setState({
number: this.setState.number + 1
});
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate');
if(prevProps.color !== this.prevProps.color) {
return this.myRef.style.color;
}
return null;
}
componentDidUpdate(prevProps, prevState, sanpshot) {
console.log('componentDidUpdate', prevProps, prevState);
if(sanpshot) {
console.log('업데이트되기 전 색상: ', sanpshot);
}
}
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.props.color}</p>
<button onClick={this.handleClick}>
더하기
</button>
</div>
)
}
}
- 이 컴포넌트는 각 라이프사이클 메서드를 실행할 때마다
console.log
를 출력하고, 부모 컴포넌트에서 props
로 색상을 받아 버튼을 누르면 state.number
값이 1씩 증가한다.
- getDerivedStateProps는 부모에게서 받은
color
값을 state
에 동기화하고 있으며, getSnapshotBeforeUpdate는 DOM
에 변화가 일어나기 적진의 색상 속성을 snapshot
값으로 변환하여 이것을 componentDidUpdate에서 조회할 수 있다.
- 그리고 shouldComponentUpdate 메서드에서
state.number
값의 마지막 자리 수가 4(ex. 4, 14, 24, 34 등등)로 끝나면 리렌더링을 취소한다.
2.2 LifeCycleSample 렌더링
src/App.js
파일에 다음과 같이 코드를 작성했다.
//App.js
// 랜덤 색상 생성하는 함수
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>
);
}
}
- getRandomColor 함수로 랜덤 색상을 설정했는데,
16777215
는 hex 표현으로 ffffff
이다.
- 버튼을 렌더링하고, 누를 때마다
handleClidk
메서드가 호출되게 이벤트를 설정했고, 불러온 LifeCycleSample 컴포넌트에 color
값을 props
로 설정한다.
src/LifeCycleSample.js
를 생성하여 아래와 같이 코드를 작성했다.//LifeCycleSample.js
class LifeCycleSample extends Component {
state = {
number: 0,
corlor: null,
}
myRef = null; // ref를 설정할 부분
constructor(props) {
super(props);
console.log('constructor');
}
static getDerivedStateFormProps(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);
// 숫자 마지막 자리가 4면 리렌더링 안함.
return nextState.number % 10 !== 4;
}
componentWillUnmount() {
console.log('componentWillUnmount');
}
handleClick = () => {
this.setState({
number: this.setState.number + 1
});
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate');
if(prevProps.color !== this.prevProps.color) {
return this.myRef.style.color;
}
return null;
}
componentDidUpdate(prevProps, prevState, sanpshot) {
console.log('componentDidUpdate', prevProps, prevState);
if(sanpshot) {
console.log('업데이트되기 전 색상: ', sanpshot);
}
}
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.props.color}</p>
<button onClick={this.handleClick}>
더하기
</button>
</div>
)
}
}
console.log
를 출력하고, 부모 컴포넌트에서 props
로 색상을 받아 버튼을 누르면 state.number
값이 1씩 증가한다.color
값을 state
에 동기화하고 있으며, getSnapshotBeforeUpdate는 DOM
에 변화가 일어나기 적진의 색상 속성을 snapshot
값으로 변환하여 이것을 componentDidUpdate에서 조회할 수 있다.state.number
값의 마지막 자리 수가 4(ex. 4, 14, 24, 34 등등)로 끝나면 리렌더링을 취소한다.src/App.js
파일에 다음과 같이 코드를 작성했다.//App.js
// 랜덤 색상 생성하는 함수
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>
);
}
}
16777215
는 hex 표현으로 ffffff
이다.handleClidk
메서드가 호출되게 이벤트를 설정했고, 불러온 LifeCycleSample 컴포넌트에 color
값을 props
로 설정한다.주의 ❗❗
LifeCycleSample.js
에서<p>color: {this.state.color}</p>
구문을<p>color: {this.props.color}</p>
로 고쳤다.
* 나도 모르게 state 값을 받아왔는데props
로color
값을 받아왔던 점 주의하자.
2.3 에러 잡아내기
- 방금 만든
LifeCycleSample
컴포넌트의render
함수에서 에러가 발생할 경우 브라우저에 아무것도 출력되지 않는다. - 따라서 사용자들이 당황하지 않도록
src/ErrorBoundary.js
라는 컴포넌트를 생성하여 아래의 코드를 작성했다.
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;
}
}
- 에러가 발생하면 componentDidCatch 메서드가 호출되어
this.state.error
값을true
로 업데이트한다. - 그 후,
render
함수는this.state.error
값이true
라면 에러가 발생했음을 알려주는div 태그
를 보여준다. - 사용 방법은
LifeCycleSample
컴포넌트를 감싸주면 된다.
사용자에게 에러 출력 안되도록 주의✔
그리고 state와 props가 햇갈리는데 계속 반복해서 복습해야겠다. ㅠㅠ🤦♂️
end
Author And Source
이 문제에 관하여([React] 9. 라이프사이클 메서드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@daekyeong/React-9.-라이프사이클-메서드저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)