리액트에서 LifeCycle 개념은 중요하다.
state와 props를 알맞게 관리하고 렌더링을 의도한 대로 다루려면 LifeCycle 개념을 정확히 이해해야 하기 때문이다.
이참에 주요한 몇 가지 LifeCycle 함수들을 살펴보자.
- constructor -
constructor(props) {
super(props);
this.state = { date: new Date() };
this.handleClick = this.handleClick.bind(this);
}
/ 호출 시점
> 생성자 constructor 는 컴포넌트가 마운트되기 전에 호출된다.
/ 활용 목적
> constructor 에서는 주로 state를 초기화하거나 이벤트 핸들러 메소드들을 바인딩한다.
/ 주의할 점
> 다른 구문보다도 먼저 super(props)를 실행해야 한다.
그렇지 않으면 this.props 가 정의되지 않아서 버그가 발생할 수 있다.
Uncaught TypeError: Cannot set properties of undefined (setting 'state')
> constructor에서는 this.setState() 함수를 실행하지 않고 this.state 에 값을 할당한다.
생성자 함수는 this.state에 값을 직접 할당할 수 있는 유일한 곳이다.
> constructor 에서 state를 초기화할 때 props 를 그대로 가져다가 사용하면 안 된다.
props 가 바뀌더라도 state에는 새롭게 반영되지 않기 때문이다.
props를 쓰려면 state 를 거치지 말고 직접 props 에서 꺼내서
그때 그때 this.props.color 이런 식으로 불러다 써야 한다.
constructor(props) {
this.state = { color : props.color }; // 안 좋은 예시
}
state 에 props 값을 넣어서 쓰는 작업은 불필요한 작업이다.
props 가 바뀌었을 때 state 가 바뀌었을 때와 마찬가지로 렌더링이 다시 일어나기 때문이다.
단, props 가 바뀌는 것을 의도적으로 무시하고 쓰고 싶은 경우에는 이러한 방식을 사용할 수도 있다.
- componentDidMount -
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
this.initData(this.props.userID);
}
/ 호출 시점
> 컴포넌트가 마운트된 직후, 즉 DOM 트리에 삽입된 직후에 호출된다.
/ 촬용 목적
> DOM 노드가 먼저 있어야 하는 초기화 작업은 componentDidMount 에서 하면 된다.
> 외부에서 데이터를 불러와야 한다면 네트워크 요청을 보내기 적절한 시점이다.
/ 주의할 점
> componentDidMount() 에서 setState() 를 호출하는 경우 렌더링이 추가로 발생한다.
하지만 브라우저가 화면을 갱신하기 전에 이루어지기 때문에 사용자는 알아차릴 수 없다.
이렇게 사용하는 방식은 성능 문제를 일으킬 수 있으므로 잘 써야 한다.
하지만 모달이나 툴팁처럼 렌더링하기 전에 먼저 DOM 노드의 크기나 위치를 측정해야 하는 경우 이러한 방식이 필요할 수 있다.
> 대부분의 경우는 componentDidMount() 대신에 constructor() 단계에서 초기 state 를 할당할 수 있다.
props 에 의존하는 state 가 필요할 때는 어떻게 해야 하는지 알고 싶다면 아래 글을 참고하자
https://ko.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
- componentDidUpdate -
componentDidUpdate(prevProps) {
if(this.props.userID !== prevProps.userID) {
this.fetchData(this.props.userID);
}
}
/ 호출 시점
> 갱신이 일어난 직후에 호출된다. 렌더링이 새롭게 일어날 때마다 실행된다고 이해하면 편하다.
> 단 최초 렌더링에서는 호출되지 않는다.
/ 활용 목적
> 컴포넌트가 갱신되었을 때 DOM을 조작하고 싶다면 componentDidUpdate 가 적절한 시점이다.
> 이전 props 와 새로운 props 를 비교하여 네트워크 요청을 보내야 할 때 사용해도 좋다.
/ 주의할 점
> props 를 그대로 state 에 넣어서 사용하는 것은 좋지 않다.
되도록이면 state 를 거치지 않고 props 를 직접 사용하는 것이 좋다.
이점은 constructor 나 componentDidMount 와 비슷하다.
> componentDidUpdate 는 전달 인자로 이전 props 를 받아온다.
이 props 를 활용하여 특정한 값이 바뀌는지 감지하도록 조건문으로 감싸야 한다.
조건문이 없다면 렌더링이 무한 반복하여 발생할 수 있다.
/ 고급
> 만약 컴포넌트에서 getSnapshotBeforeUpdate() 를 구현했다면 componentDidUpdate() 의 동작이 조금 달라진다.
getSnapshotBeforeUpdate() 가 return 하는 값은 componentDidUpdate() 에 세 번째 전달인자로 넘어온다.
또한 getSnapshotBeforeUpdate() 가 false 를 return 한다면 componentDidUpdate 는 실행되지 않는다.
만약 getSnapshotBeforeUpdate() 를 구현하지 않았다면 세 번째 파라미터는 undefined 로 넘어온다.
- componentWillUnmount -
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
/ 호출 시점
> 컴포넌트가 마운트 해제되어 제거되기 직전에 호출된다.
/ 활용 목적
> 타이머 제거, 네트워크 요청 취소, 구독 해지 등 정리해야 하는 작업들이 있다면 componentWillUnmount 가 적절한 시점이다.
/ 주의할 점
> 이제 컴포넌트가 다시 렌더링되는 일 없이 아주 사라지므로 setState() 를 호출하면 안 된다.
> 참고
https://ko.reactjs.org/docs/react-component.html
- 221108
'React' 카테고리의 다른 글
[React] onChange 값이 한 박자씩 늦게 들어갈 때 / observable 변수 렌더링 뒤늦게 반영될 때 (0) | 2023.01.02 |
---|---|
[React] + dataGrid 트리 구조 테이블에서 합계 구하는 법 (feat. 재귀 함수) (0) | 2022.12.12 |
[React] componentDidUpdate 사용 시점과 무한 루프 렌더링 주의 (0) | 2022.11.28 |
React 시작하기 - 09 - textarea, input, select 등 폼 form 태그 다루기 (0) | 2022.06.18 |
React 시작하기 - 08 - 리스트 반복문으로 엘리먼트 만들기, key 개념 (0) | 2022.06.18 |