2019-08-05 TIL

2019-08-05

리액트 라이프사이클 관련

리액트 라이프사이클 메서드 특히 shouldComponentUpdate 나 componentWillReceiveProps는 외부에서 state나 props를 변경할 때만 호출된다고 생각했는데

외부가 아닌 내부에서 state가 변해도 실행된다.

componentWillReceiveProps는 mount시점에는 실행되지 않고, props가 변하지 않더라도, 부모가 재 렌더되면 실행된다.

테스트시 부모의 내부 state 변화(setTimeout으로 setState수행. 외부에서 내려온 변화 없음)에 의해 재 렌더 되었고, 이에 따라 자식 컴포넌트 역시 재 렌더되었다.

constructor! 
render! 
NESTED] constructor! 
NESTED] render! 
NESTED] componentDidMount! 
componentDidMount! 
--- 부모의 내부 state변화 ---
shouldComponentUpdate! 
render! 
NESTED] componentWillReceiveProps!  Object {props: true}  Object {}
NESTED] shouldComponentUpdate!  Object {props: true}  Object {nested: "a"}
NESTED] render!

Code Sandbox

그런데!!!!!

componentWillReceiveProps는 리액트 17부터는 삭제될 예정이다.

정확히는 componentWillMount componentWillReceiveProps componentWillUpdate 세 개가 다음과 같은 순서로 제거된다.

  • 16.3: UNSAFE_componentWillMount, UNSAFE_componentWillReceiveProps, UNSAFE_componentWillUpdate (UNSAFE_ 안붙은 메서드도 유지)
  • A future 16.x release: componentWillMount, componentWillReceiveProps, componentWillUpdate. (이전 버전과 같지만 dev모드에서 deprecate warning 표출)
  • 17.0: componentWillMount, componentWillReceiveProps, componentWillUpdate (이 시점 부터는 UNSAFE_ 붙은 메서드만 유지)

componentWillReceiveProps 관련 참고할 내용

출처: 한재엽님 블로그

Two important notes:

  1. props가 변경되지 않아도 componentWillReceiveProps는 실행하기 때문에 this.propsnextProps를 비교하는 것이 중요합니다.
  2. componentWillReceiveProps은 해당 컴포넌트가 mounted 되기 전에 실행되어 새로운 props를 받습니다. 이것은 React가 mount 중에는 초기 props에 대해 componentWillReceiveProps를 호출하지 않는다는 것을 의미합니다.

추가 내용

React version 16에서 componentWillReceiveProps를 사용하여 상태를 변경할 때는 동기적으로업데이트 해야 합니다.(dispatch request 또는 setTimeout과 같은 비동기적 요청은 해당 메소드에서 처리하면 안 됩니다.)
React Fiber 를 사용하면 라이프 사이클이 진행되기 전에 componentWill[*] 메서드가 여러 번 호출 될 수 있습니다. props이 변경될 때 상태를 비동기적으로 업데이트하려면 componentDidUpdate를 사용해야 합니다.

최신 라이프사이클

출처: 공식문서

Mounting

Updating

Unmounting

다이어그램도 있다. (구글에 react lifecyle 치면 이미지에 늘 나오는 그것)

From Classes to Hooks (공식문서)

How do lifecycle methods correspond to Hooks?

  • constructor: Function components don’t need a constructor. You can initialize the state in the useState call. If computing the initial state is expensive, you can pass a function to useState.

  • getDerivedStateFromProps: Schedule an update while rendering instead.

  • shouldComponentUpdate: See React.memo below.

  • render: This is the function component body itself.

  • componentDidMount, componentDidUpdate, componentWillUnmount: The useEffectHook can express all combinations of these (including less common cases). => 다이어그램에서 이 세 라이프사이클 메서드이 모두 side effect를 실행하는 역할을 한다는 것과 연관되는 네이밍이다!

  • componentDidCatch and getDerivedStateFromError: There are no Hook equivalents for these methods yet, but they will be added soon.


Hooks와 기존 라이프사이클이 완전히 대응되는 것인지는 모르겠다. 대응 될 필요가 있는걸까? 라이프사이클 메서드 개념에서 벗어나야 하는걸까? Hooks는 과연 기존 라이프사이클 메서드를 엮어서 만든것일까?

이제부터는 Hooks를 파헤쳐보자


Minchang Kim
Minchang Kim
웹/앱 개발자 김민창입니다! 좋은 하루 되세요!