LoginSignup
36
18

More than 5 years have passed since last update.

React コンポーネント作成時に非同期通信したいときは componentDidMount に書こう

Last updated at Posted at 2017-09-30

componentWillMount vs componentDidMount

「React コンポーネントを画面に表示する際に、サーバーからデータを非同期で取得して、その結果を表示に使う」というのはよくあることかと思いますが、その非同期通信処理はどこに書けばよいでしょうか?パッと浮かぶのは次のどちらかでしょう:

  • componentWillMount()
  • componentDidMount()

どちらに書くべきなのか調べてみました。

結論: componentDidMount の方がよい

表題の通りですが、componentDidMount() の方がよいみたいです。理由は下記。

プログラマーに誤解を与えない

componentWillMount() 内に setState() を書くと、なんとなく render() までに state が設定完了するように錯覚してしまいがちです。ですが、一般に非同期通信は render() 実行までに完了するとは限りません。例えば下記のコードは、データフェッチに時間がかかる場合、 render() 実行時に this.state.items を参照できずエラーになってしまいます(コードは https://daveceddia.com/watch-out-for-undefined-state/ より引用)。

class Quiz extends Component {
  componentWillMount() {
    axios.get('/thedata').then(res => {
      this.setState({items: res.data});
    });
  }

  render() {
    return (
      <ul>
        {this.state.items.map(item =>
          <li key={item.id}>{item.name}</li>
        )}
      </ul>
    );
  }
}

正しく動作させるには、下記のようなコンストラクタを書いて、初期値を設定する必要があります。

  constructor(props) {
    super(props);
    this.state = {
      items: []
    };
  }

「Will」の代わりに「Did」を使うことで、書き手は事前にコンストラクタで state の初期化が必要なことを意識しやすいですし、読み手も「通信が完了するまでに初期値で一瞬描画されるんだな」ということが理解しやすくなります。

componentWillMount は2回実行されることがある

いわゆる isomorphic な設計の場合、componentWillMount() はサーバーサイドとクライアントサイドで計2回実行されてしまうそうです。これに関しては私が isomorphic について無知なため詳しく説明できません。すみません・・・。

所感

A と B の2つの機能のうちどちらを使うか悩んだとき、「A だと X が実現できるが B ではできないから」といった論理的な理由をつい求めがちですが、「A の方が人にやさしいから」という理由でもいいんだよなあ、という気づきを得ました。

参考

36
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
18