원래 하려던 것: 클래스 컴포넌트에서 쓰이는 생명 주기 메서드를 함수형 컴포넌트에서 적용하려면 어떻게 해야하는지 다시 정확하게 알기
먼저 알고 싶은 것: 클래스 컴포넌트에서 쓰이는 생명 주기 메서드
따라서,
State와 생명주기에서 다시 시작
- render 메서드는 업데이트가 발생할 때마다 호출되지만, 같은 DOM 노드로 <Clock />을 렌더링하는 경우 Clock 클래스의 단일 인스턴스만 사용된다. 따라서 로컬 state와 생명주기 메서드 등의 기능을 사용할 수 있다.
- 어플리케이션에 컴포넌트가 삭제될 때, 해당 컴포넌트가 사용 중이던 리소스를 확보하기
- 타이머가 DOM에 렌더링 될 때(마운팅), DOM에서 삭제될 때 각각 componentDidMount, componentWillUnmout
예시로 나온 <Clock />
1. <Clock />가 ReactDOM.render()로 전달 → Clock 컴포넌트의 constructor를 호출 → 현재 시각이 포함된 객체로 this.state를 초기화
2. Clock 컴포넌트의 render( ) 메서드를 호출 → 화면에 표시되어야 할 내용 확인 → Clock의 렌더링 출력값을 일치시키기 위해 DOM을 업데이트
3. Clock 출력값이 DOM에 삽입 // → // componentDidMount( ) 생명주기 메서드를 호출 → Clock 컴포넌트는 매초 컴포넌트의 tick( ) 메서드를 호출하기 위한 타이머를 설정하도록 브라우저에 요청
4. 매초 브라우저가 tick() 메서드를 호출 → Clock 컴포넌트, setState( )에 현재 시각을 포함하는 객체를 호출하면서 UI 업데이트를 진행→ state가 변경된 것을 인지하고 화면에 표시될 내용을 알아내기 위해 render( ) 메서드를 다시 호출→ render( ) 메서드 안의 this.state.date가 달라지고 렌더링 출력값은 업데이트된 시각을 포함→ DOM을 업데이트
5. Clock 컴포넌트가 DOM에서 삭제되면 componentWillUnmount 호출
state에 대해 기억할 것
- 직접 수정 금지. 대신 setState 사용 (직접 수정하면 렌더링이 일어나지 않음)
- state 업데이트는 비동기적일 수도 있음 (성능 때문. 단일 업데이트로 한꺼번에 처리)
- 대신 setState에 객체가 아닌 함수를 인자로 넘겨줄 수도 있음.
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
- 업데이트는 병합됨. 변수를 독립적으로 업데이트할 수 있음. (그동안 destructuring으로 다른 변수들도 같이 업데이트 했는데 그럴 필요 없는 듯)
- state는 로컬 또는 캡슐화. props로 자식한테 넘겨줄 수는 있음.
컴포넌트 생명주기
마운트 - 업데이트 - 제거
projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
마운트
: 인스턴스 생성되어 DOM에 삽입될 때의 순서
🔹 constructor ( )
- 메서드를 바인딩하거나
- state를 초기화
- 마운트 되기 전에 호출
🔹 render( )
🔹 componentDidMount( ) : 마운트 직후, 트리에 삽입된 직후. DOM 노드가 있어야 하는 초기화 작업
- 즉시 setState를 호출하는 경우 ( 내 경우 ) : 추가적인 렌더링이 발생한다. render( )가 두 번 호출되지만 브라우저가 화면 갱신하기 전에 이루어져서 사용자는 중간 과정을 볼 수 없음.
=> constructor( ) 에서 초기 state 할당할 수 있음
=> Modal이나 툴팁처럼 렌더링 전에 DOM 노드의 크기나 위치를 먼저 측정해야 하는 경우에는 이러한 방식이 필요
업데이트
: props 또는 state가 변경되었을 때 컴포넌트가 다시 렌더링되면 다음의 순서대로 호출
🔹 render( )
- React 엘리먼트
- 배열과 Fragment
- Portal; 별도의 DOM 하위 트리에 자식을 렌더링
- 문자열과 숫자; 텍스트 노드로 렌더링
- Boolean 또는 null; 아무것도 렌더링하지 X
- 순수해야; 호출될 때마다 동일한 결과를 반환해야 하며, 브라우저와 직접 상호작용 X
🔹 componentDidUpdate( prevProps, prevState, snapshot ) : 갱신 직후에 호출.
- DOM 조작이나 props를 비교하여 네트워크 요청을 보내는 작업에 활용.
- 여기에서 조건문으로 감싸지 않은 채로 setState 하면 무한 루프.
- shouldComponentUpdate()가 false를 반환하면 호출되지 않음.
🔹 shouldComponentUpdate( nextProps, nextState )
- 현재 state 또는 props의 변화가 컴포넌트의 출력 결과에 영향을 미치는지 여부
- 기본값 true; state가 변화할 때마다 다시 렌더링
- props 또는 state가 새로운 값으로 갱신되어서 렌더링이 발생하기 직전에 호출
- 성능 최적화를 위함 (렌더링 방지하려면 PureComponent 사용)
🔹 getSnapshotBeforeUpdate(prevProps, prevState)
마운트 해제
🔹 componentWillUnmount( ): 마운트 해제되어 제거되지 직전에 호출.
- 타이머 제거, 네트워크 요청 취소
오류 처리
🔹 componentDidCatch( )
기타 API
사용자가 컴포넌트 내에서 직접 호출
🔹 setState(updater, [callback]): 컴포넌트 state의 변경 사항을 대기열에 집어넣고, React에게 해당 컴포넌트와 그 자식들이 갱신된 state를 사용하여 다시 렌더링되어야 한다고 알림
- 즉각적인 명령이 아니라 요청. 항상 즉각적으로 갱신 X
댓글