2019-08-13 TIL

2019-08-13

React Lifecycle Method

React의 새로운 Lifecycle Method 중 하나인 getDerivedStateFromProps가 왜 굳이 static 메서드로 만들어졌는지 사실 난 궁금해하지 않았지만 회사 동료이자 개발 선배인 Pratt의 의문을 이어받아 잠깐 찾아봤다.

static getDerivedStateFromProps 인 이유 :

StackOverflow에 공식문서와 Dan Abramov의 말을 인용해 달린 답글들이 있었다.

The idea to move all unstable things and side effects after the render method. Giving access to component instance variables during an interruptible phase may lead to people using it with all sorts of side effects causing an inconsistency in async rendering

불안정하거나 사이드이펙트가 있는 로직은 render메서드 이후 시점에 수행하도록 하려는 의도.

getDerivedStateFromProps가 render 이전에 중단가능한 시점에 호출되고, 이 때 인스턴스 변수에 접근을 허용하면 사람들로 하여금 리액트의 비동기 렌더링에 모순을 일으키는 사이드이펙트를 만드는 코드를 짜게 할 수 있다는 이유였다.

좀 간과했던 것이, 리액트는 한두사람이 만드는게 아니고, 자바스크립트처럼 proposal을 받으면 거기에 대한 충분한 논의를 통해 의사결정이 이뤄진다는 것임. 만들어진 모든 것들에 웬만하면 다 이유가 있을 것.

static method인게 어때서?

getDerivedStateFromProps가 static 메서드인 덕분에, 메서드 정의 안에서 this를 참조할 수 없다. (애초에 인스턴스에게 포함되지 않는 메서드가 된다.)

공식문서에서는 componentWillReceiveProps에 대응한다고 했으나, 이 메서드가 props의 변화에 대응하는 거의 모든 로직을 수용할 수 있기 때문에 이미 사용된 내용을 getDerivedStateFromProps로 옮기는 것이 까다로운 경우가 종종 있다. (내 생각엔 아마 리액트에서 의도하지 않은 방법으로 기존 라이프사이클 메서드를 사용하고 있던 것 같다.)

this를 참조하던 로직에서 this 사용이 금지되었다. 단순히 변수 뿐만 아니라 this.setState(..)역시 사용할 수 없다.

그렇다면 어떻게 할까? 구현 난이도 면에서는 shouldComponentUpdate를 이용하는 것이 편했다. 특히 shouldComponentUpdate를 아직 사용하지 않고 있었다면 더욱.. 어차피 true 리턴중이니까 그걸 유지시키고, 원하는 동작이 일어날 트리거 코드만 그대로 옮겨주면 되는 것.

참고로 componentWillReceivePropsgetDerivedStateFromProps 둘 다 웬만하면 사용을 자제할 것을 권하고 있다.

Both the older componentWillReceiveProps and the new getDerivedStateFromPropsmethods add significant complexity to components. This often leads to bugs. Consider simpler alternatives to derived state to make components predictable and maintainable.

두 메서드 다 컴포넌트에 상당한 복잡도를 얹어주며, 버그를 초래한다.

근데 그렇다고 대신에 shouldComponentUpdate를 사용하는게 맞는지는 아직 확신이 없다.


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