Reactガイドを読んでいくその5

これは

Reactのガイドを読んでいく記事です

ガイドのリンク

ja.reactjs.org

state とライフサイクル

今回は2回に分けます。
stateとライフサイクルについて以前作成した時計のアプリを変更しながら学習する。
目標はclockコンポーネントカプセル化して再利用可能にする。
Image from Gyazo

関数をクラスに変換する

Clock関数コンポーネントをクラスに変換する。
Clock関数↓

function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

関数コンポーネントをクラスに変換する。
●ES6クラスを作成する

class Clock extends React.Component {
    /*ここに処理が入る*/
}

●render()空メソッドを追加する

class Clock extends React.Component {
    render() {
        /*ここに処理が入る*/
    }
}

●関数の中身をrender()メソッドに移動する

class Clock extends React.Component {
    render() {
        // funcではなくなったのでその中の処理部分
        return (
            <div>
                <h1>Hello, world!</h1>
                <h2>It is {props.date.toLocaleTimeString()}.</h2>
            </div>
        );
    }
}

●移動したfunction部分は不要なので削除する

以上でクラスとして定義されるようになりました。
renderメソッドは更新ごとに呼ばれるが、DOMのノード内でをレンダーしている限りClockのインスタンスは1つだけになります。
こうすことでローカルのstateやライフサイクルメソッドが利用できるようになる。

クラスにローカルな state を追加する

Clockはクラスにしたので、次はdateをpropsからstateに変更します。
●render()メソッド内のthis.props.dateが対象になります。
 this.state.dateに変更します。

class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
  // stateに変更
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

●this.stateの初期化クラスコンストラクタを追加

class Clock extends React.Component {
  constructor(props) {
    // ここに注目。
   // クラスコンポーネントは常にpropsを引数として親クラスのコンストラクタを呼び出す
    super(props);
 // クラスコンストラクタの追加
    this.state = {date: new Date()};
  }

  render() {
  // 省略
  }
}

要素からdateプロパティを削除する

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

クラスにライフサイクルメソッドを追加する

コンポーネントが破棄された時にリソースの解放を行うように修正していきます。
今回のアプリケーションではタイマーという形でClockの動作を制御します。
タイマーを設定するのはDOMとしてClockが描画される時、クリアをしたいのは削除される時
設定の時をマウント、クリアのことをアンマウントと呼ぶ。

先ほど作ったクラスの中でマウント・アンマウントをするメソッドを追加します。
こういったメソッドのことをライフサイクルメソッドという。

class Clock extends React.Component {
    constructor(props) {
         // 略
    }

    componentDidMount() { }

    componentWillUnmount() { }

    render() {
       // 略
   }
}

componentDidMount()メソッド内でDOMにレンダーされた後に実行されます。
よってここにタイマーをセットするのが良い。

componentDidMount() {
 // this.timerIDとして格納していることに注目
    this.timerID = setInterval(
          () => this.tick(),
          10000
    );
}

後片付けとしてcomponentWillUnmount()で行う。

componentWillUnmount() {
    clearInterval(this.timerID);
}

Clockが毎秒実行するtick()にメソッドを実装する。

class Clock extends React.Component {
    constructor(props) {
         // 略
    }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

    render() {
       // 略
   }
}

上記で作成した処理は以下のような動きをしています。
1.ReactはがReactDOM.render()に渡されたことを検知すると、
 Clockのコンポーネントのコンストラクタを呼び出す。
 現在時刻を含んだオブジェクトで初期化を行う。
2.Reactはrender()メソッドを呼び出す。
3.Clockの出力がDOMに挿入されると、ReactはcomponentDidMount()を呼び出す。
4.ブラウザは毎秒tick()メソッドを呼び出す。ClockコンポーネントはsetState()を呼び出してUIの更新をスケジュールする。
 setState()のおかげでReacktはstateの変化を検知することができ、render()を呼び出して更新を行います。
5.ClockコンポーネントがDOMから削除されることがあればReactはcomponentWillUnmount()ライフサイクルメソッドを呼び、
 タイマーが停止する。

今日はここまで。