scramble cadenza

技術ネタのガラクタ置き場

React.js で親子関係にある component の更新順序

イントロ

話題の React.js を去年末ぐらいから、ちょこちょこと触っています。
殆ど Javascript 触ったこと無い状態から、いきなり React 始めて大分修羅の道だったのですが、最近ようやく慣れてきました。

何となくわかってきた React の性質っぽいものを残しておくメモ

これは何か

React.js で作った component の更新順序を見てみた、というもの。
結論を言ってしまうと、親子関係にあると、必ず 「親 → 子」の順序で更新が行われる

現象

React.js の基本原則として、this.setState を呼ぶと、それがトリガーになって render が呼ばれる、というものがある
(state とは Ruby でいうインスタンス変数のようなもの。setStatesetter だと思えばいい)
以下のように、子も親も同時に setState を呼ぶとどうなるのだろう?という話。

超簡単なサンプルを作ってみた。

var Parent = React.createClass({
  getInitialState: function() {
    return (
      { age: 0 }
    );
  },
  setAge: function() {
    var value = this.refs.age.getDOMNode().value;
    this.setState({ age: Number(value) });
  },
  increment: function() {
    this.setState({ age: this.state.age + 1});
  },
  render: function() {
    console.log('in parent');

    return (
      <div id="parent">
        <h2>parent</h2>
        <p>input parent age: {this.state.age}</p>
        <input type="text" ref="age"/>
        <button onClick={this.setAge}>submit</button>

        <h2>child</h2>
        <Child increment={this.increment} />
      </div>
    );
  }
});

var Child = React.createClass({
  getInitialState: function() {
    return (
      { age: 0 }
    );
  },
  increment: function() {
    this.setState({ age: this.state.age + 1});
    this.props.increment();
  },
  render: function() {
    console.log('in child');
    return (
      <div id="child">
        <p>parent age: {this.state.age}</p>
        <button onClick={this.increment}>a year ago</button>
      </div>
    );
  }
});

React.render(
  <Parent />,
  document.getElementById('parent')
);

最初に親の年齢を入力して、a year ago ボタンを押すと、子供の年齢も親の年齢も 1 インクリメントするやつ。

ところでこのアプリ、親の年齢を入力しないと、親も子も 0 歳からスタートする。0 歳の親ってどういうこっちゃ。
けど細かいところは気にしない。

サンプルの重要なところは React の render で parent から child を作ってるところ。 つまり

- parent
   - child

のような構造を作っている。

一番下の a year ago ボタンをクリックすると、console には

 in parent
 in child

と出力される。
これは先に親の render が呼ばれて、その後に子の render が呼ばれることを意味している。

で、何がいいたい?

どうしてこういう順序になるのか、わからないです。
直感的には setState が先に呼ばれた方、でも良い気もするので。

こういうもの、という理解でいいのだろうか?
「親→子」という流れは理解しやすんだけど、それで無理やり理解した気になるのもなんだかなー。