일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- list.map
- CSS
- redux
- 리사이클러뷰
- react
- useCallback
- 컬러구성
- hot Reloading
- list
- equalityFn
- 공부
- 비동기처리
- php문법
- createPortal
- useState
- typescript
- 웹
- javascript
- 리액트를 다루는 기술
- Git
- 가상회선교환
- 리덕스
- 자동반영
- async
- rebase
- await
- pull
- merge
- Kotlin
- 리액트
- Today
- Total
공부블로그
리액트 7장. 컴포넌트의 라이프사이클 메서드 본문
모든 리액트 컴포넌트에는 라이프사이클( 수명주기 )이 존재한다.
컴포넌트의 수명은 페이지에 렌더링되기 전인 준비 과정에서 시작하여 페이지에서 사라질 때 끝난다.
리액트 프로젝트를 진행하다 보면 컴포넌트를 처음으로 렌더링할 때 어떤 작업을 처리해야 하거나, 컴포넌트를 업데이트 하기 전후로 어떤 작업을 처리해야 할 수도 있고, 불필요한 업데이트를 방지해야 할 수도 있다.
이때 컴포넌트의 라이프사이클 메서드를 사용한다.
(라이프사이클 메서드는 클래스형 컴포넌트에서만 사용할 수 있고, 함수형에서는 Hooks기능을 사용해 비슷한 작업을 처리할 수 있다.)
7. 1 ) 라이프사이클 메서드의 이해
라이프사이클 메서드의 종류는 총 9가지이다.
Will 접두사가 붙은 메서드는 어떤 작업을 작동하기 전에 실행되는 메서드이고,
Did 접두사가 붙은 메서드는 어떤 작업을 작동한 후에 실행되는 메서드이다.
이 메서드들은 컴포넌트 클래스에서 덮어 써 선언함으로써 사용할 수 있다.
라이프사이클은 총 3가지 ( 마운트, 업데이트, 언마운트 ) 카테고리로 나눈다.
- 마운트 : DOM이 생성되고 웹 브라우징에 나타나는 것
컴포넌트 만들기 → constructor → getDerivedStateFromProps → render → componentDidMount
- 업데이트 : 총 4가지 경우에 업데이트
1. props가 바뀔 때 2. state가 바뀔 때 3. 부모 컴포넌트가 리렌더링될 때 → getDerivedStateFromProps
→ shouldComponentUpdate → ( true반환 시 render 호출, false반환 시여기서 작업 취소) → render ( ← 4. this.
forceUpdate 로 강제로 업데이트될 때 ) → getSnapshotBeforeUpdate→ ( 웹 브라우저상의 실제 DOM변화 )
→ componentDidupdate
- 언마운트 : 컴포넌트를 DOM에서 제거하는 것
7. 2 ) 라이프사이클 메서드 살펴보기
7. 2. 1 ) render( )함수
-
컴포넌트 모양새를 정의, 필수 메서드
-
메서드 안에서 this. props와 this. state에 접근할 수 있고 리액트 요소를 반환
-
이벤트 설정이 아닌 곳에서 setState사용 X, 컴포넌트의 DOM요소에 접근 X ( state값에 변화를 줄 때는 componentDidMount에서 처리 )
7. 2. 2 ) constructor 메서드
-
constructor( props ) { ... }
-
컴포넌트의 생성자 메서드, 초기 state설정
7. 2. 3 ) getDerivedStateFromProps 메서드
-
props로 받아 온 값을 state에 동기화, 컴포넌트가 마운트 될 때와 업데이트될 때 호출
static getDerivedStateFromProps(nextProps, prevState) {
if(nextProps.value !== prevState.value) { // 조건에 따라 특정 값 동기화
return { value: nextProps.value };
}
return null; // state를 변경할 필요가 없다면 null반환
}
7. 2. 4 ) componentDidMount 메서드
-
componentDidMount( ) { ... }
-
컴포넌트를 다 만들고, 첫 렌더링을 마친 후 실행
-
이 안에서 다른 자바스크립트 라이브러리 또는 프레임워크의 함수를 호출하거나 이벤트 등록, setTimeout...같은 비동기 작업을 처리
7. 2. 5 ) shouldComponentUpdate 메서드
-
shouldComponentUpdate( nextProps, nextState ) { ... }
-
props 또는 state를 변경했을 때, 리렌더링을 시작할지 여부를 지정
-
true 또는 false값을 반환 ( false이면 업데이트 과정 중지 )
-
현재 props와 state는 this. props와 this. state로 접근
-
새로 설정될 props와 state는 nextProps와 nextState로 접근
7. 2. 6 ) getSnapshotBeforeUpdate 메서드
-
render에서 만들어진 결과물이 브라우저에 반영되기 직전에 호출
-
반환한 값은 componentDidUpdate에서 세번째 파라미터인 snapshot으로 전달받을 수 있다
-
주로 업데이트하기 직전의 값을 참고할 때 활용 ex) 스크롤바 위치 유지
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevState.array !== this.state.array) {
const {scrollTop, scrollHeight} = this. list
return {scrollTop, scrollHeight};
}
}
7. 2. 7 ) componentDidUpdate 메서드
-
componentDidUpdate( prevProps, prevState, snapshot ) { ... }
-
리렌더링을 완료한 후 실행, DOM 관련 처리 무방
-
prevProps, prevState를 사용하여 컴포넌트가 이전에 가졌던 데이터에 접근
7. 2. 8 ) componentWillUnmount 메서드
-
componentWillUpdate( ) { ... }
-
컴포넌트를 DOM에서 제거할 때 실행
7. 2. 9 ) componentDidCatch 메서드
-
컴포넌트 렌더링 도중 에러가 발생했을 때 오류 UI를 보여준다
-
컴포넌트 자신에게 발생하는 에러는 잡을 수 없고 this.props.children으로 전달되는 컴포넌트에서 발생하는 에러만 잡을 수 있다.
componentDidCatch(error, info) { //error는 어떤 에러인지, info는 어디인지 알려준다.
this.setState({
error: true
});
console.log({ error, info });
}
7. 3 ) 라이프사이클 메서드 사용하기
LifeCycleSample. js
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 }; //부모에게서 받은 color값(props)을 state에 동기화
}
return null;
}
componentDidMount() {
console.log("componentDidMount");
}
shouldComponentUpdate(nextProps, nextState) { //false or true 값을 받아서 리렌더링 여부 결정
console.log("shouldComponentUpdate", nextProps, nextState);
return nextState.number % 10 !== 4; //숫자의 마지막 자리가 4이면 렌더링하지 않는다.
}
componentWillUnmount() {
console.log("componentWillUnMount");
}
handleclick = () => {
this.setState({
number: this.state.number + 1,
//'더하기'버튼의 onClick이벤트핸들링을 위해 number state 업데이트
});
};
getSnapshotBeforeUpdate(prevProps, prevState) {
//???
console.log("getSnapshotBeforeUpdate");
if (prevProps.color !== this.props.color) {
return this.myRef.style.color; //DOM요소의 변화 직전 색상을 snapshot으로 반환
//myRef는 <h1>이고 그 요소에서의 color 반환
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("componentDidUpdate", prevProps, prevState);
if (snapshot) {
console.log("업데이트 되기 직전 색상", snapshot); //snapshot조회
}
}
render() {
console.log("render");
const style = {
color: this.props.color, // 부모에서 설정한 props로 스타일 설정
};
return (
<div>
<h1 style={style} ref={(ref) => (this.myRef = ref)}>
{this.state.number}
</h1>
<p>color: {this.state.color} </p>
{/* this.state.color대신 this.props.color라고 해도 되는데..?*/}
<button onClick={this.handleclick}>더하기</button>
</div>
);
}
}
export default LifeCycleSample;
각 라이프사이클 메소드를 실행할 때 마다 콘솔 디버거에 기록하고,
부모 컴포넌트에서 props로 색상을 받아 버튼을 누르면 state.number 값을 1씩 더한다.
getDerivedStateProps로 부모에게서 받은 color값을 state에 동기화 ( <p>color: {this.state.color}</p> 에서 this.state.color == this.props.color )
getSnapshotBeforeUpdate는 DOM에 변화가 일어나기 직전의 색상 속성을 snapshot값으로 반환, componentDidUpdate에서 조회
shouldComponentUpdate에서 state.number값의 마지막 자리수가 4이면 렌더링을 취소하도록 설정
App. 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", //color state
};
handleClick = () => {
this.setState({
color: getRandomColor(), //랜덤 색상 생성해서 color state에
});
};
render() {
return (
<div>
<button onClick={this.handleClick}>랜덤 색상</button>{" "}
{/*버튼을 누르면 랜덤함수로 color 업데이트*/}
<LifeCycleSample color={this.state.color} />{" "}
{/* props로 color를 설정해서 랜덤색상을 받음 */}
</div>
);
}
}
export default App;
(실행화면)
랜덤색상 버튼을 누르면 글자색과 color값이 업데이트 되고, 마지막 자리수가 4인경우에는 렌더링되지 않는다.
(13 다음에 더하기 버튼을 누르면 변화가 없고 한번 더 누르면 15가 된다)
7. 3. 1 ) 에러 잡아내기
에러를 잡아주는 ErrorBoundary라는 컴포넌트를 생성해보자.
ErrorBoundary. js
import React, { Component } from "react";
class ErrorBoundary extends Component {
state = {
error: false,
};
componentDidCatch(error, info) {
//error state를 true로 업데이트
this.setState({
error: true,
});
console.log({ error, info });
}
render() {
if (this.state.error) return <div>에러가 발생했습니다.</div>; //error == true
return this.props.children;
}
}
export default ErrorBoundary;
App. js에서 LifeCycleSample컴포넌트를 감싸준다.
import ErrorBoundary from "./ErrorBoundary"; 추가
...
<ErrorBoundary>
<LifeCycleSample color={this.state.color} />
</ErrorBoundary>
이번 장에서는 컴포넌트의 라이프사이클과 라이프사이클 메서드에 대해 알아보았다.
라이프사이클 메서드는 컴포넌트 상태 변화가 있을 때마다 실행하는 메서드이고, 서드파티 라이브러리를 사용하거나 DOM을 직접 건드려야 하는 상황에서 유용하다.
'리액트 > 리액트를 다루는 기술' 카테고리의 다른 글
9강 컴포넌트 스타일링 (0) | 2021.01.20 |
---|---|
리액트 8강. Hooks (0) | 2021.01.14 |
리액트 6장. 컴포넌트 반복 (0) | 2021.01.06 |
리액트 5장. ref: DOM에 이름 달기 (0) | 2021.01.05 |
리액트 4장. 이벤트 핸들링 (0) | 2021.01.05 |