Reactのライフサイクル - React入門

Reactのライフサイクル – React入門

React入門の第9回は、Reactのライフサイクルについて解説を行います。

Reactではコンポーネントは状態の変化(ライフサイクル)により発火する様々なライフサイクルメソッドが用意されており、コンポーネントの状態に応じて色々な操作ができるようになっています。

追記(2020/4/10)
本記事ではClassコンポーネントに指定できるライフサイクルイベントについて解説を行っています。 React 16.8よりfunctionコンポーネントにライフサイクルイベントに似た機能が追加できるuseEffectが追加されましたのでそちらも参考にしてください。

useEffect / React Hooks – React入門

ライフサイクルメソッドの種類

用意されているライフサイクルメソッドは以下の7種類です

componentWillMount()

コンポーネントがマウント(配置)される直前に呼び出されるメソッド。

このメソッド内でsetStateでstateを変更すると描画時には変更されたstateで描画されます。

componentDidMount()

コンポーネントがマウント(配置)された直前に呼び出されるメソッド。

以下のように指定することで状態変化に応じた処理を行うことができます。
このメソッド内では描画されたDOMにアクセスすることができます。

componentWillReceiveProps()

コンポーネントが受け取るpropsが変化した場合に呼び出されるメソッド。
このメソッド内でsetStateでStateを変更すると描画時には変更されたstateで描画されます。

shouldComponentUpdate()

stateもしくはporpsが変更された際のコンポーネントの再描画前に呼び出されるメソッド。
このメソッドでtrueを返した場合はコンポーネントは再描画され、falseを返した場合は再描画されない。
パフォーマンスの観点から再描画を抑制したい場合に利用される。

componentWillUpdate()

コンポーネントの再描画前に呼び出されるメソッド。
前述のshouldComponentUpdate()でfalseを返している場合はこのメソッドは呼び出されない。

componentDidUpdate()

コンポーネントが再描画されたタイミングで呼び出されるメソッド。
このメソッド内では再描画されたDOMにアクセスすることができます。

componentWillUnmount()

コンポーネントが破棄(アンマウント)される前に実行されます。

ライフサイクルメソッドの指定方法

ライフサイクルメソッドは以下のようにしてclass内で直接指定を行います

//コンポーネントの作成
class Number extends React.Component {
  constructor(props) {
    super(props);
  }
  componentWillMount(){
    console.log("コンポーネントのマウント前")
  }
  componentDidMount(){
    console.log("コンポーネントのマウント後")
  }
  componentWillReceiveProps(){
    console.log("コンポーネントが受け取るpropsが変化")
  }
  shouldComponentUpdate(){
    console.log("コンポーネントがアップデートされる前1")
    return true;
  }
  componentWillUpdate(){
    console.log("コンポーネントがアップデートされる前2")
  }
  componentDidUpdate(){
    console.log("コンポーネントがアップデートされた後")
  }
  componentWillUnmount(){
    console.log("コンポーネントがアンマウントされた後")
  }
  render() {
    return (
      <div>コンポーネント<div>
    )
  }
};

ライフサイクルメソッドを利用したサンプル

以下に簡単なサンプルを用意しました。

Numberコンポーネントには上記のように状態の切り替わりに応じてconsole上にコメントを出力する処理が記述されています。

「Numberコンポーネントのマウント切り替え」ボタンをクリックすることで、Numberコンポーネントのマウント、アンマウントが切り替わります。

また、「propsの加算」をクリックするとpropsの値が加算(変化)し、「stateの加算」をクリックするとstateの値が加算(変化)していきます。

class Number extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      stateVal : 0
    };
    this.incrementState = this.incrementState.bind(this)
  }
  //Stateの加算
  incrementState(){
      this.setState({
        stateVal : this.state.stateVal+1
      });
  }
  componentWillMount(){
    console.log("コンポーネントのマウント前")
  }
  componentDidMount(){
    console.log("コンポーネントのマウント後")
  }
  componentWillReceiveProps(){
    console.log("コンポーネントが受け取るpropsが変化")
  }
  shouldComponentUpdate(){
    console.log("コンポーネントがアップデートされる前1")
    return true;
  }
  componentWillUpdate(){
    console.log("コンポーネントがアップデートされる前2")
  }
  componentDidUpdate(){
    console.log("コンポーネントがアップデートされた後")
  }
  componentWillUnmount(){
    console.log("コンポーネントがアンマウントされた後")
  }
  render() {
    return (
      <div>
        <p>props:{this.props.propVal}</p>
        <p>state:{this.state.stateVal}</p>
        <input type="button" value="stateの加算" onClick={this.incrementState} />
      </div>
    )
  }
};
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      propVal : 0,
      isComponent :false
    };
    this.incrementProps = this.incrementProps.bind(this);
    this.mountComponent = this.mountComponent.bind(this);
  }
  //propsの加算
  incrementProps(){
      this.setState({
        propVal : this.state.propVal+1
      });
  }
  mountComponent(){
      this.setState({
        isComponent : !this.state.isComponent
      });
  }
  render() {
    return (
      <div>
        <input type="button" value="Numberコンポーネントのマウント切り替え" onClick={this.mountComponent} /><br />
        {(() => {
          if (this.state.isComponent) {
            return <Number propVal={this.state.propVal} />;
          }else{
            return null
          }
        })()}
        <input type="button" value="propsの加算" onClick={this.incrementProps} /><br />
        
      </div>
    )
  }
};
 //コンポーネントの描画
ReactDOM.render(
  <MyComponent />,
  document.getElementById('app')
);

See the Pen Reactのライフサイクルメソッド by Kazuma Nishihata (@to-r) on CodePen.

このように複数のコンポーネントで構成されるReactアプリケーションではコンポーネントの状態によってアクセスできる情報や変更できる状態に制限があり、それらをコントロールするのがライフサイクルメソッドになります。

次回は、「コンポーネント間の情報の受け渡し」について解説をしていきます。