質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

3回答

1030閲覧

ReactでJSON APIの配列要素にアクセスできない。

mmmkk

総合スコア18

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

1グッド

1クリップ

投稿2018/10/19 15:08

編集2018/10/19 15:18

Rails(APIモード)からJSON APIをaxiosで取得して, Reactで表示しようとしています。
React Routerを使っているのですが、Productの個別ページのみ、mapメソッドで

TypeError: Cannot read property 'map' of undefined ProductPage src/components/ProductPage.js:6 3 | 4 | const ProductPage = ({ product }) => ( 5 | <div> > 6 | {product.reviews.map( review => { 7 | return (<ProductReview review={review} key={review.id} />) 8 | })} 9 | </div>

が表示されます。

/api/v1/products/123 での表示例は以下です。(エラーの出る箇所で console.log()で呼び出すと、console上では問題なく表示されています。)

{ "id": 123, "name": "XXXXXXXXXXXXXX", -----------省略-------------------- "reviews": [ { "id": 426, "title": "XXXXXXXXXXXXXXXXXXXXX", ----------省略--------------------- }, { "id": 475, "title": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", ----------省略--------------------- }, -------------省略----------------- ]}

以下がコードです。 import部分は省略しています。

↓App.js

const App = () => ( <BrowserRouter> <div> <Header /> <Route exact path = '/' component={ProductsIndexContainer} /> <Route path = '/products/:productId' component={ProductPageContainer} /> </div> </BrowserRouter> ) export default App;

↓ProductPageContainer.js

class ProductPageContainer extends Component { constructor(props){ super(props) this.state = { product: [] } } componentDidMount() { const { match: { params } } = this.props; axios.get(`/api/v1/products/${params.productId}.json`) .then(response => { console.log(response) this.setState({ product: response.data }) }) .catch(error => console.log(error)) } render() { return ( <ProductPage product={this.state.product} /> ); } } export default ProductPageContainer;

↓ProductPage.js mapメソッドでエラーが出ます。

const ProductPage = ({ product }) => ( <div> {product.name} //表示される {product.reviews.map( review => { //TypeError: Cannot read property 'map' of undefined return (<ProductReview review={review} key={review.id} />) })} </div> ); export default ProductPage;

↓ProductsIndexContainer.js 一応載せておきます。さらに下層のページではproduct.reviews.map は問題なく動いています。

class ProductsIndexContainer extends Component { constructor(){ super() this.state = { products: [] } } componentDidMount() { axios.get('/api/v1/products.json') .then(response => { console.log(response) this.setState({ products: response.data }) }) .catch(error => console.log(error)) } render() { return ( <div> {this.state.products.map( product => { return (<Product product={product} key={product.id} />) })} </div> ) } } export default ProductsIndexContainer;

どなたかご教授いただければ幸いです。よろしくお願いします。

Lichtenstein👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

  • マウント直後: this.state.product === [] このタイミングでエラーが出る
  • axios.get後: this.state.product === { name: '...', reviews: [....] } name が表示され始めるのはこのタイミングから

っていう挙動っぽいです。
つまりエラーがでるタイミングでは product.name も undefined なんですが、一瞬すぎて見えないのかと。

なので state の初期値を工夫するか、 axios.get 終わるまで render で return null するかで解決すると思います。

投稿2018/10/19 17:12

編集2018/10/19 17:15
set0gut1

総合スコア2413

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

mapメソッドの前にnull判定を追加したところ、無事動きました。
ありがとうございました。

ProductPage.js

const ProductPage = ({ product }) => ( <div> {product.name} {product.reviews && product.reviews.map( review => { return (<ProductReview review={review} key={review.id} />) })} </div> ); export default ProductPage;

投稿2018/10/20 11:39

編集2018/10/20 11:41
mmmkk

総合スコア18

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

こんにちは。

ProductPageContainerconstructorthis.state の初期化をしているところで、 this.state.productの初期値を、以下のように修正してみるといかがでしょうか?

修正前

class ProductPageContainer extends Component { constructor(props){ super(props) this.state = { product: [] } }

修正後

class ProductPageContainer extends Component { constructor(props){ super(props) this.state = { product: { id: 0, name: null, reviews: [], } } }

なお上記では、 APIから返される有効なproductのidは1以上であることを前提として、0を無効なidの値として初期値に使用しています。

以上、参考になれば幸いです。

追記

上記に書いた方法の他には、以下のように this.state.productnull で初期化しておいて、ProductPage のほうで propsで渡されるproduct の null チェックを追加するという手もあるかと思います。

修正後

ProductPageContainer:

javascript

1class ProductPageContainer extends Component { 2 constructor(props){ 3 super(props) 4 this.state = { 5 product: null 6 } 7 }

ProductPage:

JSX

1const ProductPage = ({ product }) => ( 2 product && ( 3 <div> 4 {product.name} 5 {product.reviews.map( review => 6 <ProductReview 7 review={review} 8 key={review.id} 9 />) 10 } 11 </div> 12 ) 13);

なお、追記ふくめて上記の回答では、(Rails側のモデルの)あるProductにReviewが1件もついていなくても、GET /api/v1/products/:id のレスポンスJSONにはreviewsプロパティは存在して、空の配列として返してくれることを前提にしています。

投稿2018/10/20 01:10

編集2018/10/20 02:27
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問