ReactJS 의 생명주기
ReactJS 의 생명주기
거의 대부분의 언어에 메모리를 할당하는 과정이 있듯 ReactJS 에도 생명 주기(Life cycle)라는 것이 있다. 필수적으로 알고 있어야 하는 것은 아니지만, 각각의 훅에서 어떠한 일이 벌어지는 지 정도는 알고 있어야 어느 훅에서 API 를 패치해와야하는지, 어떤 훅에서 DOM 자체의 이벤트 바인딩을 해제 해줘야 하는지에 대한 가이드가 생길 수 있다. 또한 ReactJS 의 경우 특정 훅을 이용하여 컴포넌트의 최적화를 할 때 역시 유용하게 사용할 수 있으므로, 자주 사용하는 생명 주기의 경우는 알고 있는 것을 추천한다.
먼저 Javascript 의 모든 생명 주기는 비슷한 흐름을 가지고 있다.
컴포넌트가 마운트가 되기 전의 훅들이 존재하며 마운트가 된 후에는 데이터의 변화에 따라 컴포넌트가 다시 랜더링 된다. 그 후, 컴포넌트의 역할이 끝남에 따라 컴포넌트가 사라지게 된다. 필자는 개인적으로는 각 생명주기에서 브레이크 포인트를 찍어서 하나 하나 확인하는 것을 추천한다.
constructor
React 의 경우 하나 하나의 컴포넌트가 class 기반으로 되어 있다. Class 에는 기본적으로 constructor
가 존재하듯 마찬가지로 React 의 컴포넌트에서도 constructor 가 존재한다. 이 훅은 우리가 만든 컴포넌트가 처음 브라우저에 생성될 떄 가장 최초로 실행되는 함수로서, 보통 컴포넌트가 가질 state 를 초기화할 때 사용한다.
1 | class App extends Component { |
getDerivedStateFromProps
Props 로 받은 데이터를 state 에 동기화를 시키려할 때 사용하는 훅으로서, Props 가 변화할 때마다 실행된다. 만약 state 의 값을 변경할 필요가 없다면 null 값을 반환해주면 된다.
1 | class ChildrenComponent extends Component { |
render
render 함수는 어떠한 DOM 을 만들지, 내부 태그에는 어떠한 값이 들어갈지에 대한 것을 결정하는 함수이다. React 컴포넌트에 Stateless Component 와 Stateful Component, 두 가지로 나뉘는데 두 종류의 컴포넌트 모두 해당 훅은 필수적으로 가지고 있어야 할 정도로 React 컴포넌트에서는 필수적인 메소드이다.
1 | class ChildrenComponent extends Component { |
componentDidMount
우리가 정의한 컴포넌트가 브라우저상에 DOM 으로 나타나게 되면 실행되는 함수이다. 이 훅에서는 D3, Chart 같은 DOM 에 해당 라이브러리에서 제공하는 UI 를 그려야할 때 그 요청을 실행하는 훅이다. 이 뿐만 아니고 API 서버에 데이터를 호출하는 함수를 해당 훅에서 실행시켜주며, 어떠한 DOM 에 이벤트를 바인딩할 때 역시 해당 훅에서 실행된다. 필자의 경우 이 훅은 인피니티 스크롤을 만들 때 사용하였다. window 자체에 onScroll 이벤트를 해당 훅에서 바인딩을 해주어 스크롤 이벤트가 발생할 때 일정 조건을 충족할 경우 API 의 데이터를 받아오도록 하였다.
1 | class ChildrenComponent extends Component { |
shouldComponentUpdate
컴포넌트가 업데이트 되는 성능을 최적화할 때 사용하는 훅으로서, 개인적으로는 생명 주기 중에 중요한 훅 중 하나라고 생각한다. 부모 컴포넌트가 랜더함수가 실행되면 자식 컴포넌트도 랜더함수가 실행된다. 부모 컴포넌트가 업데이트 되더라도 일부 자식 컴포넌트의 props 는 업데이트 되지 않는 경우가 있다. DOM 에 그리는 것이 아니라 vitual dom 에 그리는 것이라 화면에는 따로 보여지지 않지만 props가 업데이트 되지 않아도 모든 자식 컴포넌트들이 render 함수를 실행한다. 이럴 때 해당 훅을 이용하여 랜더링 함수 실행되지 않도록 막을 수 있다.
class ChildrenComponent extends Component {
state = {
value: 0,
};
shouldComponentUpdate (nextProps, nextState) {
if (nextProps === nextState)
return false;
} else {
return true;
}
}
render () {
return (
<div>
<p>MyComponent1 :{this.props.value}</p>
<p>MyComponent1 :{this.state.value}</p>
</div>
)
}
}
getSnapshotBeforeUpdate
해당 훅은 랜더 함수 실행 후, 랜더링한 결과물이 브라우저에 반영되기 바로 직전에 실행되는 함수이다. 랜더링 후 업데이트 전 스크롤의 위치 혹은 해당 돔의 크기를 가져올때 해당 훅에서 사용한다.
class ChildrenComponent extends Component {
state = {
value: 0,
};
getSnapshotBeforeUpdate (prevProps, prevState) {
// Do something
}
render () {
return (
<div>
<p>MyComponent1 :{this.props.value}</p>
<p>MyComponent1 :{this.state.value}</p>
</div>
)
}
}
componentDidUpdate
브라우저에 랜더링된 직후 실행되는 함수이다. 이전의 페이지와 현재의 페이지가 서로 다를 경우 해당 훅에서 특정 작업을 할 수 있다. 해당 훅에서는 랜더링 된 후에 실행되는 함수이므로 DOM 을 제어하는 등의 일 또한 추가해도 무방하다.
class ChildrenComponent extends Component {
state = {
value: 0,
};
componentDidUpdate (prevProps, prevState, snapshot) {
// Do something
}
render () {
return (
<div>
<p>MyComponent1 :{this.props.value}</p>
<p>MyComponent1 :{this.state.value}</p>
</div>
)
}
}
componentWillUnmount
componentDidMount 훅에서 DOM 에 이벤트를 바인딩했을 때 그 이벤트를 해제시켜줄때 해당 훅에서 시켜주면 된다. 위의 componentDidMount 훅에서 필자처럼 window 에 scroll 이벤트를 바인딩했다면 해당 훅에서 제거하면 된다.
class ChildrenComponent extends Component {
state = {
value: 0,
};
componentWillUnmount () {
widnow.removeEventListener("scroll", function () {
// Do something
})
}
render () {
return (
<div>
<p>MyComponent1 :{this.props.value}</p>
<p>MyComponent1 :{this.state.value}</p>
</div>
)
}
}