🐕 라이프사이클은
1. 모든 리액트 컴포넌트는 라이프 사이클(수명주기)가 존재한다.
2. 컴포넌트의 수명은 페이지에 렌더링되기 전인 준비 과정에서 시작하여 페이지에서 사라질 때 끝남
그런데 우리가 리액트 프로젝트를 하다보면
1. 컴포넌트를 처음으로 렌더링 할 때 어떤 작업을 처리해야하거나
2. 컴포넌트를 업데이트한 전후로 어떤 작업을 처리하거나
3. 업데이트를 방지해야하거나
같은 상황을 마주할 수 있어요
바로 이럴 때 클래스형 컴포넌트에서는 라이프 사이클 메서드를 이용해 처리를 해줍니다.
함수형 컴포넌트에서는 못써요 대신에 비슷한 작업을 Hook으로 처리할 수 있습니다.
👻라이프 사이클 메서드 9가지
라이프 사이클 메서드는 총 아홉가지가 있습니다.
will 접두사가 붙은 메서드들은 어떤 작업을 작동하기 이전에 실행되는 메서드고
Did 접두사가 붙은 애들은 어떤 작업을 작동한 후에 실행되는 메서드입니다.
라이프 사이클은 총 세가지 상태로 나누어서 볼 수 있는데
마운트 , 업데이트, 언마운트로 나눠줄 수 있습니다.
마운트 | DOM이 생성되고 웹 브라우저 상에 나타나는 것 |
업데이트 | 말그대로 컴포넌트를 업데이트하는 것 |
언마운트 | 마운트의 반대과정 컴포넌트를 DOM에서 제거하는 것을 말합니다. |
각 과정에서 어떤 일이 일어나는지는
아래로 따라오시면 됩니다.
🥶 마운트를 할 때 일어나는 일
DOM이 생성되고 웹 브라우저 상에 나타나는 과정에서
호출되는 메서드가 여럿...있습니다.
컴포넌트만들기 |
constructor : 대충 클래스 생성자 메서드(클래스 배울 때 같이 배웠죠?) |
getDerivedStateFromProps(props에 있는 값을 state에 넣을때 사용하는 메서드) |
render(우리가 준비한 UI를 하면에 render해야 보이겠죠?) |
componentDidMount(컴포넌트가 웹 브라우저 상에 나타난 후 호출하는 메서드) |
okay... constructor, render는 대충 봐도 이해가 되는데
저 이름 긴 애들이 무섭다 그죠
getDerived머시기는 하는 일을 보면 그렇게 무섭진 않고
componenetDidMount만 보면 되겠네요
1. constructor 메서드
컴포넌트 생성자이며 초기 state를 정할 수 있는 메서드로 컴포넌트를 만들 때 실행됩니다.
2. getDerivedStateFromProps
리액트v16.3이후 새로 추가된 메서드입니다.
props로 받아온 값을 state에 동기화 시키는 용도로 사용되며 마운트 될 때, 업데이트 될 때 호출 됩니다.
3. render() 함수
라이프 사이클 메서드 중 유일한 필수 메서드 입니다.
이 메서드 안에서 this.props와 this.state에 접근할 수 있고 리액트 요소를 반환합니다.
요소는 html 태그가 될수도, 따로 만들어준 컴포넌트가 될 수도 있습니다.
만약 아무것도 보여주고 싶지 않다면 null, false 값을 반환하도록 하면 됩니다.
주의사항!!!!!!!
(1)이 메서드 안에서 이벤트 설정이 아닌 곳에서 setState를 사용하면 안됩니다.
(2)브라우저의 DOM에 접근해서는 안됩니다.
(3)DOM 정보를 가져오거나 state에 변화를 줄 때는 componentDidMount에서 처리해야합니다.
4.ComponentDidMount
컴포넌트를 만들고 첫 렌더링을 다 마친 후에 실행하는 메서드입니다.
이 안에서 다른 자바스크립트 라이브러리나 프레임워크의 함수를 호출하거나
이벤트 등록,setTimeout, 네트워크 요청 등의 비동기 작업을 처리하면 됩니다.
okay... 대충 이해가 됩니다.
constructor를 호출해서 컴포넌트를 만들고
getDerivedStateFromProps로 우리가 props로 받아온 값을 state에 동기화시켜주고
render를 호출해서 화면에 컴포넌트를 나타나게 그려주고
ComponentDidMount를 호출해서
이안에서 라이브러리나 프레임워크 같은 처리를 한다.
굉장히 당연히 해야하는 일이지만 그걸 역할을 나눠서 각각 분리시켜둔거군요
🌞 컴포넌트를 업데이트 할 때 일어나는 일
컴포넌트는 다음 4가지 상황에서 업데이트를 실행합니다.
1. props가 바뀔 때
2. state가 바뀔 때
3. 부모 컴포넌트가 리렌더링 될 때
4. this.forceUpdate로 강제로 렌더링을 트리거할 때
바로 위와 같은 상황에서 다음 메서드를 호출 합니다.
업데이트를 발생시키는 요인 (props 변경, state 변경, 부모 컴포넌트 리렌더링 등) |
getDerivedStateFromProps |
shouldComponentUpdate (요기서 true 반환되면 render 호출 / false 반환되면 여기서 작업 취소) |
render [this.forceUpdate를 호출하면 shouldComponentUpdate 평가를 안하고 바로 render함] |
getSnapshotBeforeUpdate (웹 브라우저 상의 실제 DOM 변화) |
componentDidUpdate |
총 다섯가지 메서드들이 호출되는 걸 볼 수 있는데
render는 어딜가도 빠지지 않는군요 하나하나 위에부터 아래로 흝어보겠습니다.
1.getDerivedStateFromProps
마운트 과정에서도 이미 본 메서드입니다.
props의 변화에 따라 state 값에도 변화를 주고 싶을 때 사용해요
2. shouldComponentUpdate
컴포넌트가 리렌더링을 할지 말지 결정하는 메서드로 불리언 값을 반환해줍니다.
3. render
마운트 과정에서도 이미 본 메서드죠?
화면에 컴포넌트를 렌더링해줍니다.
4. getSnapshotBeforeUpdate
컴포넌트 변화를 DOM 에 반영하기 직전 호출하는 메서드입니다.
이것도 react v16.3 이후 만들어진 메서드인데
주로 업데이트 하기 직전의 값을 참고할 일이 있을 때 사용해요(스크롤 바 위치 유지라든지)
getSnapshotBeforeUpdate(prevProps,prevState) {
if(prevState.array !== this.state.array) {
const {scrollTop , scrollHeight } = this.list
return {scrollTop, scrollHeight}
}
}
이런식으로 사용할 수 있는거죠!!
스냅샷...이라는 이름이 직관적이어서 참 좋네요
5.componentDidUpdate
이 메서드는 리렌더링을 완료한 후에 실행합니다.
업데이트가 끝난 직후이기 때문에 DOM 관련 처리를 해도 상관이 없어요!
prevProps나 prevState를 사용해서 컴포넌트가 이전에 가졌던 데이터에 접근할 수도 있고
getSnapshotBeforeUpdate 메서드가 반환한 값이 있다면
여기서 그 snapshot 값을 전달받을수도 있습니다!
😋언마운트 할 때 일어나는 과정
okay 언마운트 해줘~ |
componentWillUnmount |
언마운트 할 때는 단 하나의 메서드만 호출해줘도 되는 군요
1. componentWillUnmount
컴포넌트가 웹 브라우저 상에서 사라지기 전에 호출하는 메서드입니다.
만약 componentDidMount에서 등록한 이벤트나 타이머 , 직접 생성한 DOM이 있다면
여기서 제거를 해줘야해요!
🤢라이프사이클 메서드를 실습하자
여러분들은 좋겠네요...제가 열심히 쓴 코드를 복붙하면 되니까..
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 is working ryujisu just crazy');
}
static getDerivedStateFromProps(nextProps, prevState) {
console.log('getDerivedStateFromProps crazy just ryujisu');
if (nextProps.color !== prevState.color) {
return { color: nextProps.color };
}
return null;
}
componentDidMount() {
console.log('componentDidMount is working just ryujisu crazy');
}
shouldComponentUpdate(nextProps, nextState) {
console.log(
'shouldComponentUpdate is working ryujisu crazy just',
nextProps,
nextState,
);
return nextState.number % 10 !== 4;
}
componentWillUnmount() {
console.log('componentWillUnmount');
}
handleClick() {
this.setState({
number: this.state.number,
});
}
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.props.color}</p>
<button onClick={this.handleClick}>더하기</button>
</div>
);
}
}
export default LifeCycleSample;
위 코드는 각 라이프사이클 메서드를 실행할 때마다 콘솔에 기록하고
부모 컴포넌트에서 props로 색상을 받아 버튼을 누르면 state.number를 1 더하는 코드에요
굉장히 길어보이지만 그 내부는 수많은 콘솔로그로 점철되어있습니다.
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',
};
handleClick = () => {
this.setState({
color: getRandomColor(),
});
};
render() {
return (
<div>
<button onClick={this.handleClick}>랜덤</button>
<LifeCycleSample color={this.state.color} />
</div>
);
}
}
export default App;
App.js에서 위와 같이 코드를 작성해줍니다.
LifeCycleSample을 임포트하고
랜덤으로 색을 만들어주는 함수 만들어주고
yarn start를 통해 실행시켜보겠습니다.
오우 뭔가 좀 많이 떴는데
두번씩 뜨는건 스트릭트모드여서 그런건가 싶네요
constructor 실행되고
getDerivedStateFromProps 실행되고
render 실행되고
ComponentDidMount까지 잘 실행이 되었군요!
언마운트하고 디드마운트는 왜하는건지 잘 이해가 안가지만 아무튼 첫렌더에서 진행되는
4가지 메서드가 실행된건 확인할 수 있네요
위와 같이 렌더링된 화면에 랜덤 버튼을 눌러보겠습니다
wow...
업데이트가 될 때 실행된다고 한 다섯가지 메서드가 순서대로 실행되었네요
getDerived
shoul
render
getSnapShot
DidUpdate까지 그리고 snapshot이 트루이기 때문에
업데이트 직전 색상에 대한 안내도 출력된것을 확인 가능합니다.
이렇게 라이프사이클 메서드의 흐름을 잘 알고 있으면
나중에 컴포넌트들의 성능을 개선하는데에도 아주 잘 활용할 수 있을거에요!
서드파티 라이브러리를 사용하거나 DOM을 직접 건드려야하는 상황에서 유용하고
shouldComponentUpdate는 컴포넌트가 업데이트되어야할 상황을 명확히 지정해줄 수 있다보니
컴포넌트 성능 개선에도 큰 영향을 끼친다고 하네요
🐶마지막으로 흐름도를 그려보고 끝내겠읍니다
마운트와 업데이트는 상당부분을 공유하지만
마운트 시점에만 컨스트럭터를 실행하고
업데이트할때는 shouldComponentupdate
(한글로 번역하면 아..하기싫은데 이거 진짜 해야함?정도로 번역가능할듯)
메서드가 추가로 호출되고
마운트가 아니라 업데이트를 하는게 특징이네요
이것을 계기로 라이프사이클메서드와 조금 더 친해진 것 같습니다.
여러분들도 직접 한땀한땀 코드를 쳐보시기바라요!
'react' 카테고리의 다른 글
리액트의 SPA (SIngle Page Application) (0) | 2023.03.28 |
---|---|
리액트의 성능을 최적화 해보자 프로젝트 (0) | 2023.03.27 |
커스텀 훅으로 맛있는 훅 만들기 (4) | 2023.03.19 |
useCallback을 케이크처럼 쉽게 먹는 방법 (0) | 2023.03.17 |
useMemo를 케이크처럼 쉽게 먹는 방법 (0) | 2023.03.13 |