컴포넌트 라이프사이클 이란
컴포넌트 라이프사이클은 컴포넌트의 생성부터 소멸에 이르는 일련의 이벤트로 생각할 수 있습니다. 모든 리액트 컴포넌트에는 LifeCycle을 갖습니다. LifeCycle은 세가지 카테고리로 나뉘며, 개괄적인 그림은 다음과 같습니다.
또한 컴포넌트는 LifeCycle마다 메서드를 가지고 있습니다. 이 메서드를 이용해 특정 시점에 원하는 동작을 하도록 만들 수 있습니다. 메서드에 대해서 더 자세히 알아보겠습니다.
컴포넌트 라이프사이클 메서드 알아보기
에러 처리 메서드를 제외하고 LifeCycle의 메서드는 총 8가지 입니다.
자주 사용되는 LfieCycle 메서드를 설명해보겠습니다.
1. Mounting
컴포넌트의 인스턴스가 생성되 DOM상에 삽입되는 단계입니다. Mounting은 LifeCycle이 종료될 떄까지 한 번만 일어납니다. 아래 메서드들은 이 단계에서 순서대로 호출 됩니다.
- constructor : 컴포넌트의 인스턴스를 새로 만들때마다 생성자 메서드 호출
- render: 화면에 표현될 JSX를 반환하고 화면에 그림
- componentDidMount: 컴포넌트가 화면에 모두 그려진 이후 호출됨
componentDidMount 메서드는 첫 렌더링 이후 실행됩니다. 앤드포인트에서 클라이언트로 데이터를 불러와야 하는 경우 API 호출을 하기 좋은 위치 입니다. 데이터를 받아 올 때 setState 메서드를 이용해 컴포넌트를 업데이트 할 수 있습니다.
2. Updating
props또는 state가 변경되 컴포넌트가 업데이트되는 단계입니다. 아래 메서드들이 이 단계에서 순서대로 호출됩니다.
- static getDerivedStateFromProps
- shouldComponentUpdate
- render: 데이터가 변경되면 자동으로 호출됩니다. 화면에 다시 그림
- getSnapshotBeforeUpdate
- componentDidUpdate: 화면이 다시 그려진후 호출
3. Unmounting
컴포넌트가 DOM 상에서 제거되는 단계입니다.
- componentWillUnmount: 컴포넌트가 화면에서 제거되기전 호출됩니다.
LifeCycle메서드 실행 과정
라이프사이클 메서드는 리액트에서 지정된 시점에 실행됩니다. 각각의 LifeCycle단계에서 메서드들이 실행되는 순서를 살펴보겠습니다. 부모컴포넌트와 자식컴포넌트를 하나씩만들어 실행했습니다.
1. Mounting
App.jsx
import React, { Component } from 'react';
import Child from './Child';
class App extends Component {
constructor(props) {
super(props);
this.state = {};
console.log('부모컴포넌트 => constructor 호출');
}
render() {
console.log('부모컴포넌트 => render 호출');
return <Child />;
}
}
export default App;
Child.jsx
import React, { Component } from 'react';
class Child extends Component {
constructor(props) {
super(props);
this.state = {};
console.log('자식컴포넌트 => constructor 호출');
}
render() {
console.log('자식컴포넌트 => render 호출');
return null;
}
}
export default Child;
위 코드를 실행하면 다음과 같은 결과가 출력됩니다.
Mounting 단계는 부모컴포넌트 render가 호출된 다음 자식 컴포넌트의 Mounting 단계가 실행되는 것을 알 수 있습니다. 만약에 부모컴포넌트와 자식컴포넌트가 모두 componentDidMount 메서드를 호출한다면 자식컴포넌트에서 먼저 호출 됩니다. 이는 아래 업데이트 단계를 살펴보면서 진행해 보겠습니다.
2.Updating
App.jsx
import React, { Component } from 'react';
import Child from './Child';
class App extends Component {
constructor(props) {
super(props);
this.state = {};
console.log('부모컴포넌트 => constructor 호출');
}
render() {
console.log('부모컴포넌트 => render 호출');
return <Child />;
}
componentDidMount() {
console.log('부모컴포넌트 => componentDidMount 호출');
this.setState({ updated: true });
}
componentDidUpdate() {
console.log('부모컴포넌트 => componentDidUpdate 호출');
}
}
export default App;
Child.jsx
import React, { Component } from 'react';
class Child extends Component {
constructor(props) {
super(props);
this.state = {};
console.log('자식컴포넌트 => constructor 호출');
}
render() {
console.log('자식컴포넌트 => render 호출');
return null;
}
componentDidMount() {
console.log('자식컴포넌트 => componentDidMount 호출');
this.setState({ updated: true });
}
componentDidUpdate() {
console.log('자식컴포넌트 => componentDidUpdate 호출');
}
}
export default Child;
마운트 단계에서 componentDidMount메서드 호출시 setState를 통한 컴포넌트 업데이틀시켰습니다. 위 코드를 실행시키면 다음과 같은 결과가 출력됩니다.
3.Unmounting
언마운팅은 컴포넌트 돔에서(화면에서) 제거되는 것입니다. componentWillUnmount 메서드를 실행해 보기 위해 다음과 같은 코드를 실행하겠습니다. App.js에서 componentDidMount메서드를 이용해 자식컴포넌트를 화면에서 제거합니다.
App.jsx
import React, { Component } from 'react';
import Child from './Child';
class App extends Component {
constructor(props) {
super(props);
this.state = { hasDestoryed: false };
console.log('부모컴포넌트 => constructor 호출');
}
render() {
console.log('부모컴포넌트 => render 호출', this.state);
return (
<React.Fragment>
{this.state.hasDestoryed ? null : <Child />};
</React.Fragment>
);
}
componentDidMount() {
console.log('부모컴포넌트 => componentDidMount 호출');
this.setState({ hasDestoryed: true });
}
componentDidUpdate() {
console.log('부모컴포넌트 => componentDidUpdate 호출');
}
componentWillUnmount() {
console.log('부모컴포넌트 => componentWillUnmount 호출');
}
}
export default App;
Child.jsx
import React, { Component } from 'react';
import Descendant from './Descendant';
class Child extends Component {
constructor(props) {
super(props);
console.log('자식컴포넌트 => constructor 호출');
}
render() {
console.log('자식컴포넌트 => render 호출');
return <Descendant />;
}
componentDidMount() {
console.log('자식컴포넌트 => componentDidMount 호출');
}
componentDidUpdate() {
console.log('자식컴포넌트 => componentDidUpdate 호출');
}
componentWillUnmount() {
console.log('자식컴포넌트 => componentWillUnmount 호출');
}
}
export default Child;
Descendant.jsx
import React, { Component } from 'react';
class Descendant extends Component {
constructor(props) {
super(props);
console.log('자손컴포넌트 => constructor 호출');
}
render() {
console.log('자손컴포넌트 => render 호출');
return null;
}
componentDidMount() {
console.log('자손컴포넌트 => componentDidMount 호출');
}
componentDidUpdate() {
console.log('자손컴포넌트 => componentDidUpdate 호출');
}
componentWillUnmount() {
console.log('자손컴포넌트 => componentWillUnmount 호출');
}
}
export default Descendant;
위 코드의 실행 결과는 다음과 같습니다.
라이프 사이클 메서드 호출순서
마운팅과 업데이팅 단계에서 메서드 호출 순서를 그림으로 정리하면 다음과 같다.
참고자료
[Reactjs] 컴포넌트 라이프사이클 메서드 - velog
[Reactjs] 컴포넌트 라이프 사이클과 주요 메서드 호출 순서 - Tistory
'프론트 엔드 > React' 카테고리의 다른 글
[React] create-react-app & Typescript 초기 세팅법 완벽 정리 (0) | 2021.10.21 |
---|---|
[React] useMemo와 useCallback (0) | 2021.10.13 |
[React] 리덕스 (Redux)란 ? (0) | 2021.10.12 |