리액트 생명주기
컴포넌트는 생명주기 이벤트를 갖는다. 컴포넌트의 일부분을 초기화 할 때와 외부 데이터를 가지고 올 때 그 이벤트들의 도움을 받아 쉽게 동작이 가능하다.
(사진출처 : velopert.com)
componentWillMount
컴포넌트가 처음 DOM에 마운트 될 때 ReactDOM.render()
메소드를 호출한다. 이 호출은 componentWillMount
를 트리거한다. 이 메소드에서는 내부 데이터를 변경하기위해 setState를 부를 수 있다. 하지만 새로운 렌더링 동작을 다시하거나, 이 메소드를 다시 부를수는 없다.
componentDidMount
컴포넌트를 마운트한 이후(render) 호출된다. 컴포넌트가 렌더링된 이후에 딱 한 번 실행된다. 이러한 동작을 사용해 컴포넌트의 초기 렌더링 이후에 컴포넌트를 표시할 수 있는 동적인 정보를 가져올수 있다.
//예
getInitialState: function(){
return({
changeSets: []
});
},
mapOpenLibraryDataToChangeSet: function(data){
return(
data.map(function(change,index){
return({
"when": change.timestamp,
"who": change.author.key,
"description": change.comment
});
})
);
},
//API에서 실시간 데이터를 얻기 위해 생명주기 메소드를 사용하였다.
//컴포넌트가 랜더링 된 이후 state를 변경시켰다.
componentDidMount: function(){
$.ajax({
url: 'http://openlibrary.org/recentchanges.json?limit=10',
context: this,
dataType:'json',
type: 'GET'
}).done(function(data){
var changeSets = this.mapOpenLibraryDataToChangeSet(data);
this.setState({changeSets: changeSets});
});
},
render: function(){...}
아래 코드에서는 toggleState를 통해 App 컴포넌트를 다시 랜더링한다. 이런 동작이 발생하게되면 shouldComponentUpdate
, componentWillUpdate
가 호출되는걸 확인 할 수 있다.
shouldComponentUpdate
이 메소드는 React가 컴포넌트를 렌더링할지 아닐지를 나타내기 위해 true
또는 false
를 반환한다. 즉 false
일경우 state
가 변경되어도 컴포넌트를 다시 랜더링 하지 않는다. nextProps와 nextState를 이미존재하는 값과 비교해 다시 랜더링할지 아닐지를 결정할 수 있다. (validation 같은 느낌) 이때문에 더 불필요한 랜더링을 줄이고 더 빨리 컴포넌트를 사용할 수 있다. 리액트가 만들어진 이유를 생각해보면 좋다.
componentWillUpdate
(shouldComponentUpdate
를 통과하고) 컴포넌트가 업데이트 되기 전에 호출된다. 변경사항을 관리할수 있으며, 목적대로 사용하거나 내부 관리용으로 사용할 수 있다. 주의할점은 이메소드 내에서는 setState
를 호출할 수 없다. (호출시 무한루프에 빠져들게 된다.)
componentWillReceiveProps
자식 컴포넌트가 부모 컴포넌트로부터 받은 새로운 prop(nextProps
)를 사용한다. 이메소드는 초기 렌더링시에 호출되지 않고, prop에서 변경이 있을 경우에 이를 토대로 몇몇 다른 내부관리(housekeeping)작업을 하거나 state를 업데이트 할 수 있다.
console.log("Start");
var App = React.createClass({
componentWillMount: function(){
console.log("componentWillmount");
//setup tasks before render component
//마운트되기 이전에 한번만 호출한다.
//즉 이후에 아무리 랜더가 바뀌어도 다시 호출되지 않는다.
},
componentDidMount: function(){
console.log('componentDidMount');
//call after render component mounted
//willmount 와 마찬가지로 마운트된후 한번만 호출한다.
//즉 이후에 아무리 랜더가 바뀌어도 다시 호출되지 않는다.
},
getInitialState: function(){
return({status: true});
},
getDefaultProps: function(){
return({name: 'John'});
},
componentWillReceiveProps: function(nextProps){
console.log("componentWillReceiveProps");
//prop값을 다시 받을때 render되기전 발생한다.
},
shouldComponentUpdate: function(nextProps, nextState){
console.log("shouldComponentUpdate");
return true; //또는 false
},
componentWillUpdate: function(){
console.log('componentWillUPdate');
//마운트랑 비슷하나 컴포넌트가 업데이트될때 발생
//때문에 여러번 발생가능.
},
render: function(){
console.log("render");
return(
<div>
<h1 onClick={this.toggleState}>
{this.state.status.toString()}
</h1>
</div>
);
},
componentWillUnmount: function(){
console.log('componentWillUnmount');
//마운트랑 비슷하나 컴포넌트가 업데이트될때 발생
//때문에 여러번 발생가능.
},
toggleState: function(){
this.setState({status: !this.state.status});
}
});
const rootElement = document.getElementById('root');
ReactDOM.render(
<App name="Jane"/>, rootElement
);