firebase-timestamp-cannot-render
firebase timestamp cannot render
why
単に2chなサービスを作ろうとして,NoSQLなfirestoreにはauto-incrementなid
がないから(idはあるけどrandなhex),created_at のtimestampのdataをrenderの時のsortのindexにしようとした.
何をしているか
単純なFirestoreからの読み込みとDOM render.
useCollectionを使ってShow.jsを書いている
import firebase from 'firebase/app'; import {firestore} from '../Config/config'; const ref = firebase.firestore().collection('writings');
これでconfig.jsに書いてあるapikeyなどからこのprojectのwriting tableを持ってきて
import {useCollectionData} from 'react-firebase-hooks/firestore'; const Show = () => { const [values, loading, error,] = useCollectionData( ref, {idField: 'id'}); if(loading) { return <div>Loading...</div> } if(error) { return <div>{`Error: ${error.message}`}</div> } console.log(values); return ( <Row> <Col> {values.map(value => ( <div key = {value.id}> <div> {++num}:名無しさん:{value.id}:2019.05.17 </div> <div> {value.content}type: </div> </div> ))} </Col> </Row> .........
これでuseCollectionDataを使ってvaluesにwritingsの配列を渡している.そしてrenderで value.idとvalue.contentを描画している.
これでconsoleを見ると,配列にid, content, そしてcreated_atが入っているのが見える.
ちょっと待っておちんちんナメナメってだれw
Error
timestamp
ここで問題はtimestampになる. consoleをよくみてみると
15: content: "かえでのちんちん舐め舐め" created_at: t nanoseconds: 786000000 seconds: 1589720334 __proto__: Object id: "zTBHecvjaaZOtt3kVmIt"
このようにcontentやidのように直接は入っていなくて,
t
のobjのように入っているのがわかる.
このt
はfirebase consoleをみると
timestampで入っている.timestampのtらしい.
int32とかで書かれている特殊なtype.?
よって単純に value.created_atで出力しても
react-dom.development.js:13413 Uncaught Error: Objects are not valid as a React child (found: object with keys {seconds, nanoseconds}). If you meant to render a collection of children, use an array instead.
objと中身が見つかりました,objはrenderできませんってerrorが出る.
try01 .toDate
ここで公式Docの通りに
{value.created_at.toDate}
としても
typeError: Cannot read property 'toDate' of undefined
で読み込めないと出てしまう.()をつけても同様だ.
try02 .get() about milli second
こちらのサイトでも基本的に.toDate使えと書いてある. new Dateのところはdate to tsの方.
これによると
Server側のTimestampはMicro secondだが,JS Dateはmilli second
microseconds = milliseconds * 1000 なのでtsの方が精確.
つまり細かいものから大まかなものにはできるはず.
そしてコードは
const timestamp = snapshot.get('created_at'); const date = timestamp.toDate(); // JS Date 型が欲しい場合
でかけと書いてある
{value.created_at.get().toDate()}
.get()を挟んでみたがダメだった.
try03 servertimestamp
次は
あるとしたらServerTimestampとTimestampの違いかもThinking face
Only after you have synced with Firestore and the data is fetched again, the prop will be changed from serverTimestamp → to Timestamp
However, ... FieldValue.serverTimestamp() gives nothing of value.
とあるので同じコードで同じ症状だ.
Add.jsxで
created_at: firebase.firestore.FieldValue.serverTimestamp.now(),
で書いているからね....
serverTimestamp() itself does not contain any date information, and you can't convert it to a date.
と書いてある.convertできないの辛くね?
ただ前の方に
Only after you have synced with Firestore and the data is fetched again, the prop will be changed from serverTimestamp → to Timestamp
fetchするとtimestampになって.toDateできるよって書いてあった!!これか!!!
本物のtimestampはtではなく,timestampと出るらしい...
serverTimestamp fetchで調べてもserverTimestampを入れる方法しかでなかった
hさんにまた聞きなおそう...
読み取りに行く,getと同じ処理らしいがどう書くんだろう....
04 firestoreのdata type listから
ここらへんの記事見ると、timestamp 受け取ったときに timestamp オブジェクトが Date に変換する関数をもっているみたいですね
Dateオブジェクトでクライアントのタイマー取得してもしょうがないというケースが多いと思います。サーバ時間をセットする時は下記を使います。
firebase.firestore.FieldValue.serverTimestamp()
私はサーバー(の?)時間をDBにセットしていたんだな
Firestoreから取得したドキュメントにセットされているタイムスタンプ型を扱うときはtoDate()でJSのDate型に変換します。
firebase.firestore().collection('users').doc('123').get().then(function(doc) { var timestamp = doc.data().timestamp.toDate(); }
これを真似て
{value.created_at.timestamp.toDate()}
で.timestampを挟んでみたが,どのみち
Show.jsx:31 Uncaught TypeError: Cannot read property 'toDate' of undefined
toDateはないとErrorが出てしまう
try 05 .second
ブログ読みました created_at.seconds で秒がとれそうですね
Show.jsx:31 Uncaught TypeError: Cannot read property 'seconds' of undefined
.t.secondsでも同じだった
new Date(value.created_at.seconds)
でも同じ
{(new Date(value.created_at)).toString()}
で少し進んだ!!!
俺みたいな中3でグロ見てる腐れ野郎、他に、いますかっていねーか、ははtype:Invalid Date
Invalid Dateと出る.
これで(new Date(...))の部分をなくすと
Show.jsx:31 Uncaught TypeError: Cannot read property 'toString' of undefined
となる.value.created_atにstringがない
やはり謎のt
が問題だ!!!!
{values.map(value => { console.log(value.created_at); return ""; })}
でsecがでた.
created_atが一つundefになってた
{value.created_at ? (value.created_at.toDate().toString()) : "NO DATE" }
例外処理で解決多分しました,明日テストします
これで綺麗に2ch完成しました.みてくれた方々ほんとうにありがとうございました !