

📌라이프사이클의 분류
- 리액트는 컴포넌트 기반의 View를 중심으로 한 라이브러리다.
- 각각의 컴포넌트에는 라이프사이클 즉, 컴포넌트의 수명주기가 존재한다.
- 수명은 보통
페이지에서 렌더링되기 전인 준비과정에서 시작하여 페이지에서 사라질 때 끝난다.
- 라이프 사이클은 위의 그림과 같이 총 9가지, 유형은 크게 3가지가 존재한다.
마운트
: DOM이 생성되고 웹 브라우저 상에서 나타나는 것
언마운트
: DOM에서 제거되는 것
업데이트
: 다음과같은 4가지 상황에서 발생한다
- props가 바뀔 때
- state가 바뀔 때
- 부모 컴포넌트가 리렌더링 될 때
- this.forceUpdate로 강제로 렌더링을 트리거할 때
📌라이프 사이클 메서드 살펴보기
1. constructor
- 컴포넌트를 만들 대 처음으로 실행된다.
- 초기 state 를 정할 수 있다.
super(props)
를 하는 이유는, 원래 React.Component가 지니고 있는 constructor가 존재하기 때문에, 우선 호출해야한다.
함수형
- useState hook을 사용하여 설정해줄 수 있다.
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
const Example = () => {
const [count,setCount] = useState(0);
}
2. getDerivedStateFromProps
- 리엑트 16.3버전 이후에 생긴 메서드
- props로 받아 온 값을 state에 동기화 시키는 용도로 사용한다.
- 컴포넌트가 마운트될 때와 업데이트 될 때 호출 된다.
- 예를 들어, 무엇을 움직이도록 만들지 결정하기 위하여 이전과 현재의 자식 엘리먼트를 비교하는
<Transition>
과 같은 컴포넌트를 구현할 때에 편리하게 사용할 수 있다.
함수형
- 이 기능을 대체할만한 hook이 없다.
class Example extends React.Component {
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.value !== prevState.value) {
return { value: nextProps.value }
}
return null
}
}
3. shouldComponentUpdate
- props나 state를 변경했을 때, 리렌더링을 할지 말지 결정하는 메서드.
- 반드시 true나 false를 반환해야한다.
- 성능 최적화만을 위한 것이다.
- 클래스형은 보통은 PureComponent 를 추천한다.
함수형
- porps는 React.memo를 state는 useMemo를 활용하여 성능을 개선할 수 있다.
class Example extends React.Component {
shouldComponentUpdate(nextProps) {
return nextProps.value !== this.props.value
}
}
const Example = React.memo(() => {
...
},
(prevProps, nextProps) => {
return nextProps.value === prevProps.value
}
)
4. render
- 가장 기초적이면서도
가장 중요한 메서드
이기도 하다.
- 컴포넌트를 렌더링할 때 필요한 메서드.
- 유일한 필수 메서드
함수형
- 별다른 명령어 없이 컴포넌트를 렌더링 할 수 있다.
class Example extends React.Component {
render() {
return <div>컴포넌트</div>
}
}
const example = () => {
return <div>컴포넌트</div>
}
5. getSnapshotBeforeUpdate
- render에서 만들어진 결과가 브라우저에 실제로 반영되기 직전에 호출된다.
- 가장 마지막으로 렌더링된 결과가 DOM 등에 반영되기 전에 호출된다.
- 채팅 화면처럼 스크롤 위치를 따로 처리하는 작업이 필요한 UI 등을 생각해볼 수 있다.
- 이 메서드를 사용하면 컴포넌트가 DOM으로부터 스크롤 위치 등과 같은 정보를 이후 변경되기 전에 얻을 수 있다.
- 이 생명주기 메서드가 반환하는 값은
componentDidUpdate()
에 세번째 인자로 전달된다.
함수형
- 이 기능을 대체할만한 hook이 없다.
class Example extends React.Component {
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current
return list.scrollHeight - list.scrollTop
}
return null
}
}
6. componentDidMount
- 이 메서드는 컴포넌트를 만들고 첫 렌더링을 마친 후 실행.
- 외부API를 호출하거나, 브라우저에 나타난 DOM에 직접 접근이 가능하므로 특정 DOM에 event를 걸어줄 수도 있다.
함수형
- useEffect hook 을 사용한다.
- useEffect의 deps를 비워줘야지만 똑같은 메소드를 구현할 수 있다.
class Example extends React.Component {
componentDidMount() {
...
}
}
const Example = () => {
useEffect(() => {
...
}, []);
}
7. componentDidUpdate
- 이것은 리렌더링을 완료한 후 실행한다.
- 업데이트가 끝난 직후이므로, DOM관련 처리를 해도 무방하다.
getSnapshotBeforeUpdate()
에서 반환하는 값을 3번째 인자로 받는다.
함수형
- useEffect hook 을 사용한다.
class Example extends React.Component {
componentDidUpdate(prevProps, prevState) {
...
}
}
const Example = () => {
useEffect(() => {
...
});
}
8. componentWillUnmount
- 이 메서드는 컴포넌트를 DOM에서 제거할 때 실행한다.
- componentDidMount에서 등록한 이벤트가 있다면 여기서 제거 작업을 해야한다.
함수형
- useEffect의 CleanUp 함수를 통해 구현이 가능하다.
class Example extends React.Component {
coomponentWillUnmount() {
...
}
}
const Example = () => {
useEffect(() => {
return () => {
...
}
}, []);
}
9. componentDidCatch
- 마지막으로 맨 위의 사진에는 보이지 않지만 componentDidCatch라는 메서드가 존재한다.
- 이 메서드는 컴포넌트 렌더링 도중에 에러가 발생 했을 때 애플리케이션이 멈추지 않고 오류 UI를 보여줄 수 있게 해준다.
함수형
- 이 기능을 대체할만한 hook이 없다.
class Example extends React.Component {
componentDidCatch(error, info) {
console.log('에러가 발생했습니다.')
}
}
📌Hook에서 사용못하는 Lifecycle method들은??
- 우리의 목표는 Hook이 class의 모든 사용 사례를 가능한 한 빨리 커버하게 하는 것입니다. 드문
getSnapshotBeforeUpdate
, getDerivedStateFromError
및 componentDidCatch
생명주기에 해당하는 Hook은 아직 없지만, 곧 추가할 계획이다. (리액트공식문서 참고)
📌react의 setState (hook에서는 useState)를 왜 사용하는지
- 불변성(immutable)을 유지해야 한다.
- 리액트가 웹 상에 렌더링 되기 위해선 render() 메서드가 실행되어야한다. ( 위에 공부 내용을 참고하면, state가 변경될 때 업데이트 사이클이 실행이되고, 그 때 shouldComponentUpdate 가 true이면 render() 함수가 실행이된다는걸 알 수 있다. )
- 값이 변경 되었다는걸 판단하기 위해 리액트는 객체로 저장된 state를 비교 연산을 하는데, 객체는 참조에 의한 전달을 한다.
- 그러므로 새로운 주소값에 할당된 새로운 객체를 만들어주는 setState나 useState 를 사용해야한다.
- 추가적인 사항
- setState는 비동기적으로 동작하기 때문에 state가 직접 수정되어 여러번 상태를 업데이트 하는 경우, 이전 업데이트 내용이 다음 업데이트 내용에 덮어 쓰여질 수가 있다. 즉, 예상치 못한 곳에서 버그가 발생 할 수 있다.
- PureComponent에서 동작하지 않는다. PureComponent는 this.state와 setState를 비교해 업데이트가 필요한 경우에만 render함수를 호출해 준다. 이때, state를 직접 수정하게되면 기존의 this.state와 setState가 동일하므로 리액트는 render함수를 호출하지 않는다.
📌Reference
good...!