2.3 getDerivedStateFromProps 메서드
2.6 getSnapshotBeforeUpdate 메서드
● 정리
모든 리액트 컴포넌트에는 라이프사이클 메서드가 존재한다.
컴포넌트의 수명은 페이지에 렌더링되기 전 ~ 페이지에 사라질 때까지이다.
라이프사이클 메서드는 클래스형 컴포넌트에서만 사용할 수 있다.
함수 컴포넌트의 경우 Hooks 기능을 사용하여 처리한다. ➨ 8장
#라이프사이클 메서드: 생명주기 메서드라고도 한다. 마운트, 업데이트, 언마운트 때에 호출되는 메서드들을 말한다.
라이프사이클 메서드의 종류는 총 9가지이다.
라이프사이클은 마운트, 업데이트, 언마운트로 나뉜다.
컴포넌트가 업데이트하는 경우
render() {...}
컴포넌트의 모양(웹 페이지에 보이는 UI)을 정의한다. 라이플사이클 메서드 중 필수로 사용해야하는 메서드이다.
이 메서드 안에 this.props와 this.state에 접근할 수 있고, 리액트 요소(div 태그, 컴포넌트 등)를 반환한다.
웹페이지에 아무것도 보여주고 싶지 않을 때 ➨ null 또는 false를 반환한다.
# this.props와 this.state는 현재 웹페이지에 보이는 값이다.
※주의사항
➨ DOM 정보를 가져오거나 state에 변화를 줄 때에는 componentDidMount에서 처리한다.
constructor(props){...}
컴포넌트의 생성자 메서드로 컴포넌트를 만들 때 처음으로 실행되는 메서드이다.
이 메서드에서 초기 state를 설정할 수 있다.
static getDerivedStateFromProps(nextProps, prevState) {
if(nextProps.value != = prevState.value) {
return { value: nextProps.value };
}
return null; //state 값을 변경할 필요 없을 경우, null 반환
}
props로 받아온 값을 state에 동기화시키는 용도로 사용하는 메서드이다.
컴포넌트가 마운트, 업데이트될 때 호출된다.
componentDidMount() { ... }
마운트 과정에서 호출되는 메서드로, 컴포넌트를 만들고 첫 렌더링을 마친 후에 실행되는 메서드이다.
메서드 내에서 js 라이브러리 또는 프레임워크 함수 호출,
이벤트 등록과 setTimeout, setInterval 네트워크 요청등의 비동기 작업을 처리한다.
shouldComponentUpdate(nextProps, nextState) { ... }
props 또는 state가 변경되었을 시, 리렌더링 시작의 여부를 정하는 메서드이다.
메서드에서 true 또는 false 값을 반환하며, 컴포넌트를 만들 때 이 메서드를 생성하지 않으면 항상 true를 반환한다.
➨ 이는 props 또는 state가 업데이트 됐을 때 항상 리렌더링 과정을 거친다.
메서드 내에서 현재 props와 state는 this.props와 this.state, 새로 설정될 props와 state는 nextProps와 nextState로 접근할 수 있다.
getSnapshotBeforeUpdate(prevProps, prevState) {
if(prevState.array != = this.state.array) {
const { scrollTop, scrollHeight } = this.list
return { scrollTop, scrollHeight };
}
}
render에서 만들어진 결과가 웹 브라우저에 실제로 반영되기 직전에 호출되는 메서드이다.
이 메서드에서 반환되는 값은 comoponentDidUpdate 메서드의 세 번째 매개변수로 전달 받는다.
업데이트하기 직전의 값을 참고할 일이 있을 때 활용된다.
ex) 스크롤바 위치 유지
componentDidUpdate(prevProps, prevState, snapshot) { ... }
리렌더링을 완료한 후 실행되는 메서드이다. 업데이트 과정이 끝난 직후라 DOM에 대한 처리가 가능하다. prevProps와 prevState를 사용하여 컴포넌트가 이전에 가졌던 데이터에 접근할 수 있다.
componentWillUnmount() { ... }
컴포넌트를 DOM에서 제거할 때 사용하는 메서드이다. componentDidMount에서 등록한 이벤트, 타이머, 직접 생성한 DOM 등을 이 메서드로 제거한다.
componentDidCatch(error, info) {
this.setState({
error: true
});
console.log({ error, info });
}
컴포넌트 렌더링 도중 에러가 발생했을 때 오류 UI를 보여주는 메서드이다.
➨ 에러를 잡아내는 방법은? 7.3절 '에러 잡아내기'
//LifeCycleSample.js
import { 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 };
}
return null;
}
componentDidMount() {
// 첫 렌더링 후 실행
console.log("componentDidMount");
}
shouldComponentUpdate(nextProps, nextState) {
console.log("shouldComponentUpdate", nextProps, nextState);
return nextState.number % 10 !== 4; //숫자의 마지막 자리 수가 4이면 => false를 반환
}
componentWillUnmount() {
//컴포넌트를 DOM에서 제거할 때
console.log("componentWillUnmount");
}
handleClick = () => { //4장 이벤트 핸들링
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 (
<>
<h1 style={style} ref={(ref) => (this.myRef = ref)}>
{this.state.number}
</h1>
<p>color: {this.state.color}</p>
<button onClick={this.handleClick}>더하기</button>
</>
);
}
}
export default LifeCycleSample;
// App.js
import { Component } from "react";
import LifeCycleSample from "./LifeCtcleSample";
//랜덤 색상 생성
function getRandomcolor() {
return "#" + Math.floor(Math.random() * 16777215).toString(16);
}
class App extends Component {
state = {
color: "#000000",
};
handleClick = () => {
this.setState({
color: getRandomcolor(),
});
};
render() {
return (
<>
<button onClick={this.handleClick}>랜덤 색상</button>
<LifeCycleSample color={this.state.color}></LifeCycleSample>
</>
);
}
}
export default App;
에러를 의도적으로 발생시키기 위해 다음 render()를 수정한다.
render()에서 오류가 발생하는 경우는?
// LifeCycleSample.js
render() {
console.log("render");
const style = {
color: this.props.color,
};
return (
<>
{this.props.missing.value} <!--에러 발생-->
<h1 style={style} ref={(ref) => (this.myRef = ref)}>
{this.state.number}
</h1>
<p>color: {this.state.color}</p>
<button onClick={this.handleClick}>더하기</button>
</>
);
}
존재하지 않는 props인 value를 조회해서 렌더링하려고 했기 때문에 오류가 발생한다.
Uncaught TypeError: Cannot read properties of undefined (reading 'value') at LifeCycleSample.render
개발자는 개발자 도구를 통해 에러의 내용을 확인할 수 있지만 사용자가 웹 서비스를 실제로 사용할 때는 흰 화면만 나타날 것이다.
➨ 에러가 발생했다고 사용자에게 인지시켜주는 작업이 필요하다.
//ErrorBoundary.js
import {Component} from 'react';
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;
}
}
//App.js
render() {
return (
<>
<button onClick={this.handleClick}>랜덤 색상</button>
<ErrorBoundary>
<LifeCycleSample color={this.state.color}></LifeCycleSample>
</ErrorBoundary>
</>
);
}
}
ErrorBoundary로 LifeCyclesample을 감싸준다.
1. 라이프사이클은 총 3가지로 (마운트), (업데이트), (언마운트) 카테고리로 나뉜다.
2. DOM이 생성되고 웹 브라우저 상에 나타나는 과정을 (마운트)라고 한다.
3. 업데이트는 아래 경우에 웹 페이지의 업데이트 과정이 실행된다. 빈칸을 채워보자!
4. (getDerivedStateFromProps)은/는 마운트 과정과 업데이트 과정에서 호출되는 메서드로, props의 변화에 따라 state 값에도 변화를 주고 싶을 때 사용하는 메서드이다.
5. shouldComponentUpdate 메서드는 (리렌더링)을/를 시작할 지의 여부를 정하는 메서드이다. 이 메서드에서는 항상 (true) 또는 (false)를 반환하다.
6. render 함수 내에서 (this.props)와 (this.state)에 접근할 수 있으며, (리액트 요소)를 반환한다. 웹 페이지에 아무것도 보여주고 싶지 않을 때, (null) 또는 (false)를 반환하도록 처리한다
7. componentDidCatch 메서드는 컴포넌트 렌더링 도중 (에러)(이)가 발생했을 때 호출되는 메서드이다.
1. 에러를 잡아주는 에러 컴포넌트 코드를 작성하기. 에러가 발생했을 때, 호출되는 함수는 componentDidCatch 함수이다.
import { Component } from "react";
class ErrorBoundary extends Component {
state = {
error: false,
};
componentDidCatch(error, info) {
}
render() {
}
}
export default ErrorBoundary;
2. 다음 코드는 밑의 웹 페이지에 대한 코드의 일부이다. 빈칸을 코드로 채워보자!
constructor(props) {
//컴포넌트를 처음 생성할 때 실행되는 메서드
}
static getDerivedStateFromProps(nextProps, prevState) {
// 마운트, 업데이트될 때 실행되는 메서드
if ( ) { // 조건에 충족하면
//return을 통해 prop에서 받아온 값을 state에 동기화
}
return null;
}
shouldComponentUpdate(nextProps, nextState) { // 리렌더링의 여부를 결정하는 메서드
//숫자의 마지막 자리의 수가 4이면 => false를 반환하도록 작성한다.
}
Corner React Starter #2
Editor 유숨숨
<리액트를 다루는 기술> 9장: 컴포넌트 스타일링 (0) | 2022.01.03 |
---|---|
<리액트를 다루는 기술> 8장: Hooks (0) | 2021.12.27 |
<리액트를 다루는 기술> 6장: 컴포넌트 반복 (0) | 2021.11.29 |
<리액트를 다루는 기술> 5장: ref: DOM에 이름 달기 (0) | 2021.11.22 |
<리액트를 다루는 기술> 4장: 이벤트 핸들링 (0) | 2021.11.15 |