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

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

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

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JavaScript

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

API

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

React.js

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

Q&A

解決済

1回答

5687閲覧

Reactでpropsの値がundefined

yk_00

総合スコア15

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JavaScript

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

API

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

React.js

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

0グッド

1クリップ

投稿2019/07/24 10:12

前提・実現したいこと

ReactとDjangoでブログを作っています。
Django REST framework で作ったcomment APIにaxiosでコメントの一覧を引っ張ってくることに成功しました。
それは全ての記事につけられたコメントであるため、目的の記事につけられたコメントを抽出しなければなりません。
comment APIではtarget_postという値が決められており、どの記事につけられたコメントなのかを示します。

js

1if (item.target_post === this.props.articleID) return true;

これがfilterの条件です。
this.props.articleIDの値がundefinedになるためフィルターに1つもコメントが引っかかりません。

発生している問題・エラーメッセージ

プログラムは全く変えていませんが、うまくいくときとうまくいかないときがあります。
comment res.dataがapiからとってきたデータで、
this.state.commentがfilterにかけて残ったデータです。
####失敗
失敗
####成功
成功

該当のソースコード

Comment.js

js

1import React from 'react'; 2import axios from 'axios'; 3 4import { Card } from 'antd'; 5 6class CommentComponent extends React.Component { 7 8 constructor(props) { 9 super(props); 10 this.state = { 11 comment: {}, 12 } 13 } 14 15 16 17 componentDidMount() { 18 console.log("this", this); 19 axios.get('http://127.0.0.1:8000/api/v1/comment') 20 .then(res => { 21 let commentData = res.data.filter((item, index) => { 22 console.log('comment res.data: ', res.data); 23 console.log('this.props.articleID: ', this.props.articleID); 24 if (item.target_post === this.props.articleID) return true; 25 }); 26 this.setState({ 27 comment: commentData 28 }); 29 console.log('this.state.comment: ', this.state.comment); 30 }) 31 } 32 33 render() { 34 return ( 35 <div> 36 <Card title=<h1>Comments</h1>> 37 <p 38 style={{ 39 fontSize: 14, 40 color: 'rgba(0, 0, 0, 0.85)', 41 marginBottom: 16, 42 fontWeight: 500, 43 }} 44 > 45 </p> 46 <Card 47 style={{ marginTop: 16 }} 48 type="inner" 49 title="Inner Card title" 50 > 51 Inner Card content 52 </Card> 53 <Card 54 style={{ marginTop: 16 }} 55 type="inner" 56 title="Inner Card title" 57 > 58 Inner Card content 59 </Card> 60 <Card 61 style={{ marginTop: 16 }} 62 type="inner" 63 title="Inner Card title" 64 > 65 Inner Card content 66 </Card> 67 </Card> 68 </div> 69 ); 70 } 71 72} 73 74export default CommentComponent; 75

ArticleDetailView.js

js

1import React from 'react'; 2import axios from 'axios'; 3 4import { Card } from 'antd'; 5import CustomForm from '../components/Form'; 6import CommentComponent from '../components/Comment'; 7 8class ArticleDetail extends React.Component { 9 10 state = { 11 article: {} 12 } 13 14 componentDidMount() { 15 const articleID = this.props.match.params.articleID; 16 axios.get(`http://127.0.0.1:8000/api/v1/${articleID}`) 17 .then(res => { 18 this.setState({ 19 article: res.data 20 }); 21 console.log('article res.data: ', res.data); 22 }) 23 } 24 25 render() { 26 console.log('this.state.article.id', this.state.article.id); 27 return ( 28 <div> 29 <Card title=<h1>{this.state.article.title}</h1>> 30 <p>{this.state.article.text}</p> 31 </Card> 32 <CommentComponent articleID={this.state.article.id}/> 33 <Card title=<h1>Add New Comment</h1>> 34 <CustomForm 35 requestType="post" 36 target_post={this.state.article.id}/> 37 </Card> 38 </div> 39 ); 40 } 41} 42 43export default ArticleDetail; 44

試したこと

渡す値をarticle.idからarticleに変えてもダメでした。

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんにちは

React コンポーネントのライフサイクル図をいろいろな方が描いてますが、たとえば以下の図

の左上の点線で囲んだ Initialization と書かれた部分を見ても分かるとおり、componentDidMount は初回の render の後に呼ばれます。

従って、ArticleDetail の初回の render が実行される時点では、this.state.article は初期値として設定された空オブジェクトのままですので、 this.state.article.id は undefined であり、

jsx

1<CommentComponent articleID={this.state.article.id}/>

で渡した先の CommentComponent においても、 this.props.articleID が undefined になります。

このようなときによくやる手としては、ArticleDetailrender で、まずthis.state.article.id に妥当な値が入っているかをチェックして、入っていないときは、サーバーと通信中であることを示すローディングアイコンを返させることです。

例えばローディングアイコンのコンポーネントを Loading として作ったとして、以下のようにします。

** ArticleDetailView.js: **

jsx

1import Loading from '../components/Loading' 2

妥当な Article ID は整数であると仮定しますと、以下のように、 render の先頭で this.state.article.id に整数が入っているかをチェックして、入っていなければローディングアイコンを返すようにします。

jsx

1render() { 2 // 以下の2行を追加 3 if (!Number.isInteger(this.state.article.id)) 4 return <Loading />; 5 6 console.log('this.state.article.id', this.state.article.id); 7 return ( 8 <div> 9 <Card title={<h1>{this.state.article.title}</h1>}> 10 ・・・

もし、 妥当な Article ID が1以上の数であれば、if条件は if (this.state.article.id > 0) などでもよいでしょう。

上記のようにすると、Articleを取得するAPI(GET /api/v1/${articleID})が成功で返ってくるまでの間はローディングアイコンが表示され、成功で返ってくると、再度renderが実行され、そのときは、this.state.article.id にはAPIで返された Article のIDが入っているので、ローディングアイコンではなく、 <div> 以下のコンポーネントが返されます。このようにすれば、 CommentComponent がrender されるときには、必ず this.props.articleID に(undefinedではない)適正なIDの値が渡されてくることになります。

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

投稿2019/07/24 12:33

編集2019/07/24 13:23
jun68ykt

総合スコア9058

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

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

yk_00

2019/07/24 13:09

仰る通りLoadingコンポーネントを作ることで解決しました。 確かにライフサイクルの理解は曖昧でした。 自分では解決できなかったでしょう。 ありがとうございます!
jun68ykt

2019/07/24 13:11

どういたしまして。解決されたようで、よかったです ????
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問