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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

React.js

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

Q&A

解決済

2回答

776閲覧

firestoreに登録ずみのデータをreactで表示したい。

human9

総合スコア5

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

React.js

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

0グッド

0クリップ

投稿2021/07/08 10:27

前提・実現したいこと

firestoreに登録したデータをReactでwebアプリ上に表示したいです。
firestoreの公式ドキュメントを参考に実装しているのですが、コンソールログに表示することはできてもHTML上に表示させることができません。

該当のソースコード

react.js

1export default function Games(){ 2 3 var docRef = db.collection("games").doc("1Cg3grPdahBGuAC2WKnY"); 4 const game = ["0", "a"]; 5 6 docRef.get().then((doc) => { 7 if (doc.exists) { 8 console.log("Document data:", doc.data().name); 9 game.push(doc.data().name); 10 console.log(game); 11 } else { 12 // doc.data() will be undefined in this case 13 console.log("No such document!"); 14 } 15 }).catch((error) => { 16 console.log("Error getting document:", error); 17 }); 18 19 //pushしたデータがなくなっている 20 console.log(game); 21 22 return( 23 <div> 24 <ul> 25 {game.map((name, i) => <li key={i}>{name}</li>)} 26 </ul> 27 </div> 28 ) 29}

試したこと

最後のコンソールログでgame配列にpushしたdoc.data().nameの値だけ消えて、元から入っていた0とaは残っていることが確認できました。
game配列がローカルで変更されていて関数をでた後に初期値に戻ったのが原因だと思うのですが、これを解決する方法がわかりません。
配列に値を挿入した後にreturn game;と追記しても内容は変わりませんでした。

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

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

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

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

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

hoshi-takanori

2021/07/09 00:59

React で状態を扱う方法と、Firebase (に限らず) の非同期処理のやり方を理解する必要があるかと…。
human9

2021/07/09 20:47

useStateを使って動かすことはできました。 質問のソースコードの通りにやっても上から処理されるなら問題なく動くと思うのですが、なぜ状態管理を使わないと動かないのでしょうか?
guest

回答2

0

自己解決

useEffect(() => {処理}, [変数])
と書くと変数の値が変化したタイミングで処理が行われるらしいです。
State変数を変数に、レンダー処理を処理の部分に入れることで、State変数が変化するたびに表示内容が変化するという使い方が多いようですが、変数部を空にすると初めてページがレンダーされた時だけ処理を実行するようにできるそうです。
docRef.get().then以降の処理をuseEffectに入れて無限ループは解決できました。
なぜ無限ループが起きたかは全くわかっていません。

react

1useEffect(() => { 2 docRef.get().then((doc) => { 3 //非同期処理が成功したときの処理 4 if(doc.exists){ 5 games.push(doc.data().name); 6 return games; 7 } else { 8 console.log("No such document!"); 9 } 10 }).then((games) => { 11 //game配列の値がgamesの値に置き換えられる 12 setGame(games); 13 }).catch((error) => { 14 //非同期処理が失敗したときの処理 15 console.log("Error getting document:", error); 16 }); 17 }, [])

投稿2021/07/12 02:03

human9

総合スコア5

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

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

0

useStateを使うことでうまくいきました。
return gameで値を返せなかった理由は、返り値がpromiseであるためその後の処理もthenやcatchで行う必要があるからみたいです。

React

1import React,{useState} from "react"; 2import "firebase/firestore"; 3import {db, storage} from "../base"; 4 5 6export default function Games(){ 7 var docRef = db.collection("games").doc("1Cg3grPdahBGuAC2WKnY"); 8 const [game, setGame] = useState([]); 9 let games = [] 10 11 docRef.get().then((doc) => { 12 //非同期処理が成功したときの処理 13 if (doc.exists) { 14 games.push(doc.data().name); 15 //promiseと変数gamesを返す(※この後もthenやcatchでしか処理できない) 16 return games; 17 } else { 18 // doc.data() will be undefined in this case 19 console.log("No such document!"); 20 } 21 }).then((games) => { 22 //useStateでgameの値をgamesに置き換える 23 setGame(games); 24 }).catch((error) => { 25 //非同期処理が失敗したときの処理 26 console.log("Error getting document:", error); 27 }); 28 29 return( 30 <div> 31 <ul> 32 {game.map((name, index) => <li key={index}>{name}</li>)} 33 </ul> 34 </div> 35 ) 36}

投稿2021/07/09 20:43

human9

総合スコア5

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

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

hoshi-takanori

2021/07/10 09:25

Firebase のアクセスは useEffect を使わないと無限ループになりますね…。 return games; の前に console.log(games); とかすると確認できるはず。
human9

2021/07/11 02:47

useEffectについて調べてきました。 useEffect(() => { docRef.get().then((querySnapshot) => { ... } },[]) の形で非同期処理全体をuseEffect内に入れることで処理を一回に抑えたのですがあっていますか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問