• React는 component는 상위 component에서 받은 props 를 input으로 하고 React를 구성하는 가장 작은 단위인 Element 를 output으로 하는 함수
이다.
• React에는 Lifecycle이 있다.(React는 생명주기를 가지고 있음)
• 생성자를 통하여 필요한 메모리를 할당하고, 객체의 역할이 끝나면 소멸자를 통하여 메모리를 반환.
→ 컴퓨터의 자원은 한정적이라 역할이 끝나면 모든 메모리를 반환해야 메모리 누수에 문제가 생기지 않고, 더 좋은 성능 발휘 가능
리액트는 컴포넌트 기반의 View를 중심으로 한 라이브러리이다. 그러다보니 각각의 컴포넌트에는
라이프사이클
즉, 컴포넌트의수명 주기
가 존재한다. 컴포넌트의 수명은 보통 페이지에서 렌더링되기 전인 준비 과정에서 시작하여 페이지에서 사라질 때 끝이난다.
: Lifecycle은 보기와 같이 총 9개가 존재함.
출처: http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
Each component in React has a lifecycle which you can monitor and manipulate during its three main phases.
리액트에서 각각의 컴포넌트는 3개의 주된 단계에서 모니터하고 조정할 수 있는 Lifecycle이 있다.
The three phases are: Mounting, Updating, and Unmounting.
3개의 단계: 마운팅, 업데이팅, 언마운팅
• React를 사용하면 각 component 단위로 UI를 화면에 보이게 하거나 다른 UI로 변경하고, 현재 보이는 UI를 화면에서 제거 할 수 있다.
• 따라서 각각의 Component들은 생성(Mounting) -> 업데이트(Updating) -> 제거(Unmounting) 단계를 차례로 겪는 생명주기(Life Cycle)를 가지고 있다.
• 리액트는 웹에서 UI데이터가 변경되면 자동으로 컴포넌트가 업데이트되며 동적으로 화면을 그림.
→ 제대로 된 기능을 수행하려면 이런 자동으로 업데이트되는 과정에 끼어들어 API를 호출하기도 하고 데이터를 가공하기도 해야함. 따라서, 생명주기의 각 단계별로 필요한 순간에 필요한 작업들을 끼워넣을 수 있는 메서드들이 존재한다.
: DOM이 생성되고 웹브라우저에 나타나는 것
(component가 새롭게 생성되는 시점, component 함수가 실행 → 가상 DOM에 삽입 → 실제 DOM 업데이트)
1. constructor(생성자)
: 클래스의 인스턴스 객체를 생성하고 초기화하는 특별한 메서드
• React 컴포넌트의 constructor는 해당 컴포넌트가 생성시 호출
• React.Component를 상속한 컴포넌트의 생성자를 구현할 때에는 다른 구문에 앞서 super(props)를 호출
→ 그렇지 않으면 this.props가 생성자 내에서 정의되지 않아 버그로 이어질수도!
• this.props, this.state에 접근이 가능하고 리액트 요소를 반환!
❗️주의사항
: 메서드를 바인딩하거나 state를 초기화하는 작업이 없다면, 해당 React 컴포넌트에는 cunstructor를 구현하지 않아도 됩니다.
// constructor 기본 구조
class MyComponent() extends React.Component{
constructor(props){
super(props)
//...
}
}
// super 함수를 호출해야 React.Component class의 method가 호출 됨.
// super를 호출하지 않으면? 컴포넌트 작동 ❌
2. static getDerivedStateFromProps()
•props로부터 파생된 state를 가져옵니다. 즉 props로 받아온 것을 state에 넣어주고 싶을때 사용
• 해당 API 는 props 로 받아온 값을 state 로 동기화 하는 작업을 해줘야 하는 경우에 사용.
❗️주의사항:
• 정적 메서드기 때문에 this를 호출할 수 없음.
• 이 메서드는 이유와 상관없이 렌더링 때마다 매번 실행되므로 주의.
static getDerivedStateFromProps(props,state){
// 여기서는 setState 를 하는 것이 아니라
// 특정 props 가 바뀔 때 설정하고 설정하고 싶은 state 값을 리턴하는 형태로 사용.
/*
if (nextProps.value !== prevState.value) {
return { value: nextProps.value };
}
return null; // null 을 리턴하면 따로 업데이트 할 것은 없다라는 의미
*/
}
• 최초 마운트 시와 갱신 시 모두에서 render
메서드를 호출하기 직전에 호출
• state
를 갱신하기 위한 객체를 반환하거나, null
을 반환하여 아무 것도 갱신하지 않을 수 있음
3. render
• 최종적으로 component에서 작업한 결과물을 return하는 method.
• component 라면 반드시 있어야 하는 method임!
• 함수형 컴포넌트에서는 render를 안쓰고 컴포넌트를 렌더링 가능
• React Element : 보통 JSX 를 사용하여 작성
❗️주의사항:
• Render() method는 순수(Pure Function)해야 함. (input에 대해서 같은 output이 나와야 한다는 것을 의미)
• DOM에 HTML을 표현
• 필수 메서드임!!!!!
• 시점이나 상황에 따라 다른 결과물을 리턴하는 것을 지양해야 함
render() {
return (
<div>
<header className="title">
Yuntroll React
</header>
</div>
);
}
: 결과물로 나온 Element들이 Virtual DOM에 mount되고 실제 DOM에 업데이트됨.
4. componentDidMount
• 컴포넌트가 마운트(트리에 삽입)된 직 후 호출(컴포넌트가 마운트 될 때 한 번만 호출)
• 여기선 주로 D3, masonry 처럼 DOM 을 사용해야하는 외부 라이브러리 연동을 하거나, 해당 컴포넌트에서 필요로하는 데이터를 요청하기 위해 axios, fetch 등을 통하여 ajax 요청을 하거나, DOM 의 속성을 읽거나 직접 변경하는 작업을 진행함
→ DOM이 렌더링 되기 전에 DOM에 접근하게 되면 에러가 발생하기 때문
• 일반적으로 이 메서드에서비동기 API
를 사용
→ 응답받은 외부 데이터는 내부 컴포넌트 상태에 저장되어 컴포넌트가 업데이트 되면 render() 메서드가 실행
예시코드
import React, { Component } from "react";
class UserListClass extends Component {
state = {
loading: true,
users: [],
};
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((users) => this.setState({ users, loading: false }));
}
render() {
const { loading, users } = this.state;
if (loading) return <div>Loading...</div>;
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
}
코드출처: https://www.daleseo.com/react-hooks-use-effect/
그러면 무엇을 기준으로 Updating 되는가?
- Props가 변경됨
- State가 변경됨
- 부모 component가 rerendering 됨
- this.forceUpdate로 강제로 렌더링을 trigger하는 경우
→ input이 달라지니 output도 달라져야 해서
→ 상위 component가 update되면 하위 component도 rendering 다시 mount
1. componentWillReceiveProps
• 컴포넌트가 새로운 속성을 전달받을 때 실행
• 컴포넌트에 새로운 속성을 받아오는 시점에 끼어들어서 render()를 호출하기 전에 일부 로직을 추가 가능
• 해당 메서드는 새로운 속성을 인자로 받음
• 컴포넌트 최초 실행할때는 렌더 ❌
• setState() 메서드를 호출해도 추가로 다시 렌더링이 발생 ❌
• 속성 값의 변경과 상관없이 (부모 구조 또는 호출에 따라) 재렌더링이 이뤄질 때마다 실행
→ newProps가 항상 현재 속성과 다른 값이라고 가정할 수 없음
예시코드
componentWillReceiveProps(newProps) {
this.setState({
opacity: (newProps.isVisible) ? 1 : 0
})
}
: 기존 속성 값은 this.props 객체에 있음. 예를 들어 다음의 예제 코드는 불 값인 isVisible을 기준으로 하여, CSS에 사용할 opacity 상태 값을 변경한다(true이면 1, false이면 0).
출처: https://thebook.io/006961/part01/ch05/06/01/
2. shouldComponentUpdate
• props나 state를 변경 시, 리렌더링을 할지 말지 결정하는 메서드.
• 해당 메서드는 반드시 true 혹은 false를 반환해야함.
(해당 함수는 기본적으로 true를 반환, 조건에 따라 false 를 반환하면 해당 조건에는 render 함수를 호출 ❌)
• 오직성능 최적화
만을 위한 것이며 렌더링 목적을 방지하는 목적으로 사용하게된다면 버그로 이어질 수 있음
예시코드
shouldComponentUpdate(nextProps, nextState) {
// return false 하면 업데이트 ❌
// return this.props.checked !== nextProps.checked
return true;
}
3. getSnapshotBeforeUpdate
• 업데이트 되기 직전에 snapshot(props & states)을 확보하는게 목적
• 인자값에서 반환되는 prevProps와 prevState는 변경되기 전에 값을 보여줌
• 컴포넌트에 변화가 일어나기 직전의 DOM 상태를 가져와서 특정 값을 반환하면 그 다음 발생하게 되는 componentDidUpdate 함수에서 받아와서 사용
ex) 렌더링을 하고 나서 업데이트하기 전에 스크롤의 위치, 해당 DOM의 크기 등을 가져오고 싶을 때 사용
예시코드
getSnapshotBeforeUpdate(prevProps,prevState){
// DOM 업데이트가 일어나기 직전의 시점입니다.
return {};
}
❗️ 주의사항
• componentDidUpdate의 세번째 인자로 들어감
• 해당 함수와 componentDidUpdate 함수를 함께 적지 않는 경우 Warning 발생
4. componentWillUpdate()
• 새로운 속성이나 상태를 받은 후 렌더링 직전에 호출(초기 렌더링 시에는 호출 ❌)
• 주로 갱신 전에 필요한 준비 작업을 처리할 때 해당 메서드 사용(사용시 this.setState사용은 피하자! → 갱신중에 갱신...???)
• shouldComponentUpdate()가 false를 반환하면 해당 메서드는 실행 ❌
• 컴포넌트를 DOM에서 제거할 때 실행
• componentDidMount에서 등록한 이벤트, 타이머, 직접 생성한 DOM이 있다면 여기서 제거 작업 해야함!!!
예시코드
componentWillUpdate(nextProps, nextState){
}
5.componentDidUpdate
• state나 props가 변경되어 DOM 변화가 발생한 뒤 발생(리렌더링을 완료한 후 실행, 처음 렌더링 될때는 호출❌)
• 업데이트가 끝난 직후이므로, DOM관련 처리를 해도 무방
• prevProps 또는 prevState를 사용하여 컴포넌트가 이전에 가졌던 데이터에 접근 가능⭕️
❗️ 주의사항
• componentDidUpdate()
에서 setState()
를 즉시 호출할 수도 있지만, ... 조건문
으로 감싸지 않으면 무한 반복이 발생할 수 있다는 점에 주의해야함( break와 같은역할을 가진 조건문을 걸어줘야함, 실제 변경이 일어난 경우만 작동하도록 코드 작성)
예시코드
// Class
class Example extends React.Component {
componentDidUpdate(prevProps, prevState, snapshot) {
...
}
}
: DOM에서 제거되는 것, JSX 에 포함되었다가 이후에 제거되는 경우에 발생
언마운트 예시
return <div>
{value ? <Comp1 /> : <Comp2 />}
<button onClick={() =>
setValue(!value)}>change</button>
</div>;
→ 초기에 value 가 true 인 상황에서 버튼을 클릭하면 Comp1 은 언마운트되고 Comp2 는 마운트 됨
→ 또 버튼을 클릭하면 Comp2 는 언마운트되고 Comp1 은 마운트 됨
<Comp1 key={value} />
→ key 가 변하는 경우도 언마운트 됨
→ 위 코드에서 value 가 변할 때마다 Comp1 는 언마운트되고 새로운 Comp1 이 마운트 됨
1. componentWillUnmount()
• 타이머를 제거하거나, DOM 요소를 정리하거나, componentDidMount()에서 연결한 이벤트를 제거가능
• 컴포넌트가 화면에서 사라지기 직전에 호출
• 외부 라이브러리를 사용한게 있고, 해당 라이브러리에 dispose 기능이 있다면 여기서 호출!
예시코드
class Example extends React.Component {
coomponentWillUnmount() {
...
}
}
1. componentDidCatch
• 컴포넌트 렌더링 도중에 에러가 발생 했을 때 애플리케이션이 멈추지 않고 오류 UI를 보여줄 수 있게 함
예시코드
// Class
class Example extends React.Component {
componentDidCatch(error, info) {
console.log('에러가 발생했습니다.')
}
}