리액트 생명주기

컴포넌트는 생명주기 이벤트를 갖는다. 컴포넌트의 일부분을 초기화 할 때와 외부 데이터를 가지고 올 때 그 이벤트들의 도움을 받아 쉽게 동작이 가능하다.

(사진출처 : 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
);

results matching ""

    No results matching ""