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

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

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

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

JavaScript

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

React.js

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

Q&A

0回答

1234閲覧

コンポーネントのトップレベルとarray.map()内で非同期処理をしたい。

MajinBoo

総合スコア16

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

JavaScript

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

React.js

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

0グッド

0クリップ

投稿2020/06/17 08:48

編集2020/06/17 11:44

前提・実現したいこと

ReactとFirebaseを使い、ユーザーがテキストを投稿するアプリを作成しています。
下記はデモです。
demo(CodeSandBox)
CodeSandBoxでFirebaseの諸機能を動かす方法が分からなかったため、上記のデモは全く機能しないもののFirebaseで使うメソッドを書いています。


実現したい流れは下記の通りです。

  1. Appコンポーネントがレンダーされたら、投稿データをデータベースから取得する
  2. Postデータに含まれるユーザー名から、ユーザーデータをデータベースから取得する
  3. 投稿データにユーザーデータを添えて、array.map()でレンダーする

投稿データのユーザー名はnullを許容します。
イメージとしては、アカウントを持っていなくても投稿できて、アカウントを持っている人がいたらユーザー名を添える、という感じです。

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

Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.

エラーをググっても意味は理解できなかったのですが、コンポーネントのトップレベルでasync/awaitを使うことはできないとは、なんとなく肌感覚ですが理解しておりまして、これがエラーの原因であると認識しています。

該当のソースコード

js

1const App = async () => { 2 const postsCollection = await db.collection("posts").get(); 3 const posts = postsCollection.data(); 4 5 const renderPosts = posts.map(async (item, index) => { 6 const userDocument = await db 7 .collection("users") 8 .doc(item.user) 9 .get(); 10 const user = userDocument.data(); 11 const name = user.name; 12 const address = user.address; 13 14 return ( 15 <li key={index} style={{ marginBottom: "50px" }}> 16 <p>投稿: {item.post}</p> 17 <p>名前: {name}</p> 18 <p>住所: {address}</p> 19 </li> 20 ); 21 }); 22 23 return ( 24 <> 25 <ul>{renderPosts}</ul> 26 </> 27 ); 28};

試したこと

ライブラリによってトップレベルでasync/awaitを使うことなく投稿データを取得できました。

js

1const App = () => { 2 const posts = useCollectionData(db.collection("posts"))[0]; 3 console.log(posts) // [PostA, PostB, PostC] 4 ...

同じライブラリに、コレクションではなくドキュメントのデータを取得するHooksもありました。

js

1const user = useDocumentData(db.doc("UserA"))[0];

docメソッドにはドキュメント名を渡す必要がありますが、ドキュメント名は投稿データに含まれるユーザー名を渡したいため、array.map()内で実行する必要があるかと思います。
しかし、コンポーネントのトップレベルではないためライブラリのHooksが使えない、という状態です。

そのほか、ユーザーのデータをuseState()利用し、array.map()return()に含まれるユーザーの名前と住所に渡してみました。
結果、投稿にユーザー情報を添えることができたのですが、動きがもっさりしていたのでarray.map()内でconsole.log()を記述してレンダーされた回数を確認したろ、物凄い数のレンダーが実行されていました。
そのため、パフォーマンス性を著しく損なう実装方法は避けたいです。


ライブラリを使用することにこだわりは無いです。
現状のコンポーネントのトップレベルではライブラリのHooksを使って、array.map()内では使わない、というのは綺麗ではないと思います。
ただ現状は、コードの綺麗さよりも機能を実装することを優先しています。

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

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

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

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問