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

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

新規登録して質問してみよう
ただいま回答率
85.46%
React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

JavaScript

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

React.js

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

Q&A

解決済

1回答

5080閲覧

Fetchをループさせて値を配列に入れたい(React Native, Javascript)

howareyou1245

総合スコア20

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

JavaScript

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

React.js

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

0グッド

0クリップ

投稿2020/05/31 02:26

編集2020/05/31 03:42

やりたい事

News APIとReact Nativeを使ってニュース記事などを表示させるアプリを作っています。
カテゴリーの一覧を表示するページで、カテゴリー名をタイトルにし、その下に3つ程度カテゴリーごとの記事を抽出して記載したいと考えています。
イメージはこのような形です。

【タイトル】
・記事1タイトル
・記事2タイトル
・記事3タイトル

それぞれReact Native ElementsのCardを用いて表現します。
1枚1枚のカードの表現は以下のように行っています。

javascript

1 function singleCard(title,color,items) { 2 3 return ( 4 <View style={{width:"50%"}}> 5 <Card 6 title={title} 7 containerStyle={{borderColor:color,borderWidth:2 }} 8 titleStyle={{color:color}} 9 > 10 <FlatList data={items} renderItem={({item}) => { 11 <Text>{item.title}</Text> 12 }} /> 13 </Card> 14 </View> 15 ) 16 }

そして上記の関数をもとに、カテゴリーすべてのカードを取得する関数を定義しています。

javascript

1 function Cards() { 2 let element = [] 3 let topNews = [] 4 5 categories.map((data,i) => { 6 7 var url = "https://newsapi.org/v2/top-headlines?"+'country=jp&'+'apiKey=(myapikey)&'+'category='+data +"&pageSize=3" 8 var req = new Request(url); 9 fetch(req).then((response) => response.json()) 10 .then((result) => ( 11 topNews.push(result.articles) 12 )) 13 .then(() => { 14 const tmp = singleCard(data,colorList[i%7],topNews[i]) 15 element.push(tmp) 16 }) 17 }) 18 return ( 19 element 20 ) 21 }

やりたい事としては、

  1. カテゴリーを一つずつ選択
  2. カテゴリー名を使ってFetch
  3. topNews[i]にjsonファイルを入れる
  4. 先ほどのsingleCard関数でそれぞれのReactコンポーネントを生成
  5. element変数に4で生成したコンポーネントをpushしていく

です。

なお、カテゴリーとカラーの配列は以下です。

javascript

1 const categories = ["Business","Entertainment","General","Health","Science","Sports","Technology"] 2 const colorList = ["#c23685","#d04255","#ffea2a","#3eba2b","#1daf9e","#208dc3","#c97fb4"]

エラー内容

上記ソースにて、returnしているelementが空配列**[]**になってしまいます。

Javascriptにあまり詳しくないので、どのような書き方をすれば適切に値を得られるのかわかっていません、、。
なのでご教授いただけると幸いです。

現在できていること

javascript

1 function Cards() { 2 let element = [] 3 let topNews = [] 4 5 categories.map((data,i) => { 6 const tmp = singleCard(data,colorList[i%7]) 7 element.push(tmp) 8 }) 9 10 return ( 11 element 12 ) 13 }

先ほどのFetch部分を除いた関数は、正常に動作しました。

追記

JAVASCRIPT

1 return ( 2 <View style={{backgroundColor:"#f5f5f5",height:"100%",flexDirection:"row",flexWrap:"wrap"}}> 3 {Cards()} 4 </View> 5 ) 6コード

エラー

Objects are not valid as a React child (found: object with keys {_40, _65, _55, _72}). If you meant to render a collection of children, use an array instead.

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

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

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

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

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

guest

回答1

0

ベストアンサー

原因としてはmapの中で非同期処理を繰り返しているわけですけれども、それぞれの非同期処理が完了(Promiseがresolve)されるのを待つことなくelementがreturnされているので、初期状態の空配列になっているのだと思います。要するに処理の順番の問題ですね。このへんはPromiseの知識が必要です。Promiseを使いつつも同期的に処理するためにAsync Functionで書いてみました。なお、不要と思われる変数などは削除しています。動作確認はしていないので、もし動かなかったらごめんなさい。

js

1async function Cards() { 2 // cardsはPromiseの配列 3 const cards = categories.map((data,i) => { 4 5 const url = "https://newsapi.org/v2/top-headlines?"+'country=jp&'+'apiKey=(myapikey)&'+'category='+data +"&pageSize=3" 6 const req = new Request(url) 7 8 // Promiseを返却する 9 return fetch(req) 10 .then((response) => response.json()) 11 .then((result) => singleCard(data,colorList[i%7],result.articles)) 12 }) 13 14 // 全ての非同期処理が完了するまで待機する 15 const element = await Promise.all(cards) 16 17 return ( 18 element 19 ) 20} 21

やっていることとしては、categoriesをmap処理してSingleCardのコンポーネントに解決されるPromiseの配列(cards)に変換しています。その後、await Promise.all(cards)とすることで、全てのPromiseが解決する(非同期処理が完了する)まで待機させ、その結果をreturnしています。こうすることでelementがreturnされるときには全ての非同期処理が完了していることが保証されます。

PromiseやAsync Functionなどについては以下の記事がわかりやすい(少し長いですが)ので、参考にしてみてください。
https://jsprimer.net/basic/async/

投稿2020/05/31 02:57

markey

総合スコア355

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

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

howareyou1245

2020/05/31 03:45

早速のご回答ありがとうございます! しっかりと返り値確認できました。 Reactを扱っていらっしゃるようなので恐縮ですがもう1点質問させていただきたいです。 コンポーネントのreturn部分を追記しました。 下に記したエラーが出てしまっているのですが、原因などお分かりになりますでしょうか。
markey

2020/05/31 03:56

Cardsのreturn文を下のものに変えてみるとどうでしょうか? ``` return ( element ) ``` ↓ ``` return element ```
markey

2020/05/31 04:20

んーなんとなくわかりました。直接にコンポーネントの配列をrenderできないと思うので、cardsの返り値をmap処理させます。 ``` return ( <View style={{backgroundColor:"#f5f5f5",height:"100%",flexDirection:"row",flexWrap:"wrap"}}> {Cards().map((Card, index) => <Card key={index} />)} </View> ) ```
howareyou1245

2020/05/31 04:41

``` undefined is not a function (near '...Cards().map...') ``` となりました。 一応ですが、 ``` function Cards() { let element = [] categories.map((data,i) => { const tmp = singleCard(data,colorList[i%7]) element.push(tmp) }) return ( element ) } ``` ``` return ( <View style={{backgroundColor:"#f5f5f5",height:"100%",flexDirection:"row",flexWrap:"wrap"}}> {Cards()} </View> ) ``` ではrenderされて表示されます。 なのでCards()の返り値をいじればなんとななりそうなんですが、、
markey

2020/05/31 04:52

すいません、CardsをAync Funcitonにしたことで、Cardsの返り値もPromiseになることを忘れていました。なので、Cardsの返り値を格納するStateを用意する(そして、Promiseが解決されたら結果をそのStateにsetする)などして、そちらのStateをrenderするようにすればOKだと思います。
howareyou1245

2020/05/31 05:31

できました! お手数おかけしました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問