LoginSignup
3
4

More than 3 years have passed since last update.

ajaxで取得したデータでrenderすると、Cannot read property xx of undefined エラーになる

Last updated at Posted at 2020-01-26

問題点

例えば以下のように、バックグラウンドで取得したデータを表示させたいとします。

xxx.js
  constructor(props) {
    super(props);
    this.state = {
      result: {}
    }

    fetch("http://localhost/api/test")
      .then(response => response.json())
      .then(json => this.setState({ result: json }));
    // /api/testは、以下のようなレスポンスを返す
    //  { 
    //    test1 : "aaa",
    //    test2 : {
    //      test3 : "bbb"
    //    }
    //  }
  }

  render() {
    return (
      <div>
        <p>{this.state.result.test1}</p>        // "aaa"が表示される 
        <p>{this.state.result.test2.test3}</p>  // "bbb"が出てほしいがエラーになる
      </div>
    )
  }

このとき、this.state.result.test2.test3の部分で、以下のようなエラーが出てしまいます。
Cannot read property 'test3' of undefined
test3 の親であるthis.state.result.test2がundefinedですよ、というエラーです。

原因

恐らく、this.state.resultの中身が全部セットされる前にrenderメソッドが動いてしまっているためだと思います。

解決法

1.描画前にチェックを行う

undefinedチェックを入れてあげると、エラーなく動くようになります。

xxx.js
  render() {
    return (
      <div>
        <p>{this.state.result.test1}</p>        // "aaa"が表示される 
        <p>{this.state.result.test2 ? this.state.result.test2.test3 : ""}</p>  // "bbb"が表示される
      </div>
    )
  }

JSX内ではif文が使えないので、三項演算子を使っています。

2.あらかじめ空のプロパティをセットしておく

どのような要素が返ってくるかが最初からわかっているのであれば、以下のように予めセットしておくことでも対応できます。

xxx.js
  constructor(props) {
    super(props);
    this.state = {
      result: {      
        test2 : {}   // あらかじめ空をセットしておく
      }
    }

    fetch("http://localhost/api/test")
      .then(response => response.json())
      .then(json => this.setState({ result: json }));
  }

  render() {
    return (
      <div>
        <p>{this.state.result.test1}</p>        // "aaa"が表示される 
        <p>{this.state.result.test2.test3}</p>  // "bbb"が表示される
      </div>
    )
  }

最後に

もっといい方法がありそうな気もするので、何かわかったら追記します。

3
4
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
3
4