Saya mencoba mencari cara menampilkan cap waktu firestore di aplikasi reaksi.
Saya memiliki dokumen firestore dengan bidang bernama CreatedAt.
Saya mencoba memasukkannya dalam daftar output (mengekstraksi bit yang relevan di sini sehingga Anda tidak perlu membaca seluruh daftar bidang).
componentDidMount() {
this.setState({ loading: true });
this.unsubscribe = this.props.firebase
.users()
.onSnapshot(snapshot => {
let users = [];
snapshot.forEach(doc =>
users.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
users,
loading: false,
});
});
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const { users, loading } = this.state;
return (
<div>
{loading && <div>Loading ...</div>}
{users.map(user => (
<Paragraph key={user.uid}>
<key={user.uid}>
{user.email}
{user.name}
{user.createdAt.toDate()}
{user.createdAt.toDate}
{user.createdAt.toDate()).toDateString()}
Satu-satunya atribut yang tidak akan menyajikan adalah tanggal.
Setiap upaya di atas menghasilkan kesalahan yang mengatakan:
TypeError: Tidak dapat membaca properti 'toDate' dari undefined
Saya telah melihat posting ini , dan posting ini dan posting ini , dan posting ini dan lain-lain seperti mereka, yang menunjukkan todate bahwa () harus bekerja. Tetapi - ekstensi ini menimbulkan kesalahan bagi saya - termasuk ketika saya mencoba ekstensi toString.
Saya tahu ia tahu ada sesuatu di firestore karena ketika saya mencoba user.createdAt, saya mendapatkan pesan kesalahan ketika menemukan objek dengan detik di dalamnya.
Mengambil contoh dari Waelmas di bawah ini, saya mencoba mencatat output dari bidang sebagai:
this.db.collection('users').doc('HnH5TeCU1lUjeTqAYJ34ycjt78w22').get().then(function(doc) {
console.log(doc.data().createdAt.toDate());
}
Saya juga mencoba menambahkan ini ke pernyataan peta saya tetapi mendapatkan kesalahan yang mengatakan user.get bukan fungsi.
{user.get().then(function(doc) {
console.log(doc.data().createdAt.toDate());}
)}
Ini menghasilkan pesan kesalahan yang sama seperti di atas.
PERIKSAAN BERIKUTNYA
Satu hal aneh yang muncul ketika mencoba menemukan cara untuk merekam tanggal di Firestore yang memungkinkan saya untuk kemudian membacanya kembali, adalah ketika saya mengubah handler kirim saya dalam satu bentuk untuk menggunakan formulasi ini:
handleCreate = (event) => {
const { form } = this.formRef.props;
form.validateFields((err, values) => {
if (err) {
return;
};
const payload = {
name: values.name,
// createdAt: this.fieldValue.Timestamp()
// createdAt: this.props.firebase.fieldValue.serverTimestamp()
}
console.log("formvalues", payload);
// console.log(_firebase.fieldValue.serverTimestamp());
this.props.firebase
.doCreateUserWithEmailAndPassword(values.email, values.password)
.then(authUser => {
return this.props.firebase.user(authUser.user.uid).set(
{
name: values.name,
email: values.email,
createdAt: new Date()
// .toISOString()
// createdAt: this.props.firebase.fieldValue.serverTimestamp()
},
{ merge: true },
);
// console.log(this.props.firebase.fieldValue.serverTimestamp())
})
.then(() => {
return this.props.firebase.doSendEmailVerification();
})
// .then(() => {message.success("Success") })
.then(() => {
this.setState({ ...initialValues });
this.props.history.push(ROUTES.DASHBOARD);
})
});
event.preventDefault();
};
Itu berfungsi untuk merekam tanggal dalam database.
Bentuk entri firestore terlihat seperti ini:
Saya mencoba menampilkan tanggal di komponen ini:
class UserList extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
users: [],
};
}
componentDidMount() {
this.setState({ loading: true });
this.unsubscribe = this.props.firebase
.users()
.onSnapshot(snapshot => {
let users = [];
snapshot.forEach(doc =>
users.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
users,
loading: false,
});
});
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const { users, loading } = this.state;
return (
<div>
{loading && <div>Loading ...</div>}
<List
itemLayout="horizontal"
dataSource={users}
renderItem={item => (
<List.Item key={item.uid}>
<List.Item.Meta
title={item.name}
description={item.organisation}
/>
{item.email}
{item.createdAt}
{item.createdAt.toDate()}
{item.createdAt.toDate().toISOString()}
</List.Item>
// )
)}
/>
</div>
);
}
}
export default withFirebase(UserList);
Ketika saya mencoba membacanya kembali - menggunakan:
{item.email}
Pesan kesalahan berbunyi:
Kesalahan: Objek tidak valid sebagai anak Bereaksi (ditemukan: Stempel waktu (detik = 1576363035, nanodetik = 52000000)). Jika Anda bermaksud membuat koleksi anak-anak, gunakan array. dalam Item (di UserIndex.jsx: 74)
Ketika saya mencoba menggunakan setiap upaya ini:
{item.createdAt}
{item.createdAt.toDate()}
{item.createdAt.toDate().toISOString()}
Saya mendapatkan kesalahan yang mengatakan:
TypeError: Tidak dapat membaca properti 'toDate' dari undefined
Berdasarkan kemampuan untuk membaca kembali entri yang masuk dalam dokumen yang sama di bidang lain, saya berharap semua ini berfungsi untuk menghasilkan keluaran-bahkan jika tidak diformat seperti yang saya inginkan. Itu tidak terjadi.
PERIKSAAN BERIKUTNYA
Mengambil contoh Waelmas, saya mencoba mengikuti instruksi, tetapi di mana kita tidak mendapatkan respons yang sama adalah pada langkah pertama. Di mana Walemas mendapatkan output berdasarkan ekstensi .toDate (), saya mendapatkan pesan kesalahan mengatakan toDate () bukan fungsi.
Konsisten dengan dokumentasi Firebase, saya mencoba:
const docRef = this.props.firebase.db.collection("users").doc("HnH5TeCU1lUjeTqAYJ34ycjt78w22");
docRef.get().then(function(docRef) {
if (doc.exists) {
console.log("Document createdAt:", docRef.createdAt.toDate());
}})
Ini menghasilkan serangkaian kesalahan dengan sintaks dan saya tidak dapat menemukan jalan keluarnya.
PERIKSAAN BERIKUTNYA
Saya kemudian mencoba membuat formulir baru untuk melihat apakah saya dapat menjelajahi ini tanpa aspek otentikasi dari formulir pengguna.
Saya memiliki formulir yang menerima input sebagai:
this.props.firebase.db.collection("insights").add({
title: title,
text: text,
// createdAt1: new Date(),
createdAt: this.props.firebase.fieldValue.serverTimestamp()
})
Di mana dalam formulir sebelumnya, upaya Date () yang baru berfungsi untuk merekam tanggal dalam database, dalam contoh ini kedua bidang untuk CreatedAt dan CreatedAt1 menghasilkan entri basis data yang sama:
<div>{item.createdAt.toDate()}</div>
<div>{item.createdAt.toDate()}</div>
Saat saya mencoba menampilkan nilai tanggal, yang pertama menghasilkan kesalahan yang mengatakan:
Objek tidak valid sebagai anak Bereaksi (ditemukan: Minggu 15 Des 2019 21:33:32 GMT + 1100 (Waktu Siang Timur Australia)). Jika Anda bermaksud membuat koleksi anak-anak, gunakan array
Yang kedua menghasilkan kesalahan dengan mengatakan:
TypeError: Tidak dapat membaca properti 'toDate' dari undefined
Saya tidak dapat menemukan ide tentang apa yang harus dicoba selanjutnya.
Saya melihat posting ini yang menunjukkan bahwa hal berikut mungkin melakukan sesuatu yang bermanfaat:
{item.createdAt1.Date.valueOf()}
Tidak. Itu membuat kesalahan yang mengatakan:
TypeError: Tidak dapat membaca properti 'Tanggal' yang tidak ditentukan
Posting ini tampaknya memiliki masalah yang sama dengan saya, tetapi tidak membahas bagaimana mereka berhasil menampilkan nilai tanggal yang mereka simpan.
Posting ini tampaknya terjebak pada pesan kesalahan array, tetapi tampaknya telah menemukan cara untuk menampilkan tanggal menggunakan CreatedAt.toDate ()
Ketika Anda mendapatkan cap waktu dari Firestore, mereka berasal dari tipe berikut:
Untuk mengonversikan ini menjadi cap waktu normal, Anda dapat menggunakan fungsi .toDate ().
Misalnya, untuk dokumen seperti berikut:
Kita dapat menggunakan sesuatu seperti:
dan hasilnya akan seperti:
Sekarang untuk memproses stempel waktu lebih lanjut, Anda dapat mengubahnya menjadi string dan menggunakan regex untuk memodifikasinya sesuai dengan kebutuhan Anda.
Misalnya: (Saya menggunakan Node.js di sini)
Akan memberikan Anda output seperti ini:
sumber
Jadi firestore menyimpan kurma sebagai objek dengan detik dan nanodetik. Jika Anda ingin waktu pengguna dibuat maka Anda akan referensi
user.createdAt.nanoseconds
. Ini mengembalikan cap waktu unix.Bagaimana Anda ingin menampilkan tanggal di aplikasi Anda? Jika Anda ingin mendapatkan objek tanggal maka Anda dapat melewati timestamp ke konstruktor tanggal seperti itu
new Date(user.createdAt.nanoseconds)
. Secara pribadi saya menikmati menggunakan perpustakaan tanggal-fns untuk menangani waktu.sumber
user.createdAt && new Date(user.createdAt.nanoseconds)
. Date-fns tidak akan membantu dengan masalah ini, itu hanya pustaka praktis untuk menampilkan tanggal setelah Anda memilikinya.firestore.FieldValue.serverTimestamp()
Cara mengirim tanggal ke Firestore:
Cara membacanya kembali:
Pada dasarnya ketika Anda melakukannya,
createdAt.toDate()
Anda mendapatkan objek Tanggal JS.Saya menggunakannya seperti ini setiap saat!
Dari: https://cloud.google.com/firestore/docs/manage-data/add-data
Ini akan membuat data berdasarkan tanggal sistem pengguna. Jika Anda perlu memastikan bahwa semuanya akan disimpan secara kronologis (tanpa ada kesalahan tanggal sistem yang ditetapkan oleh sistem pengguna Anda) pada DB Anda, Anda harus menggunakan stempel waktu server. Tanggal akan ditetapkan menggunakan sistem tanggal internal DB Firestore Anda.
sumber
Dengan ID dokumen Pengguna yang memiliki
createdAt
properti yang disetel, coba yang berikut ini:Saya tidak perlu memanggil
.data()
metode sebelum mengakses properti dokumenPerhatikan bahwa jika Anda mengakses
docRef.data().createdAt.toDate()
pengguna yangcreatedAt
haknya tidak ditetapkan, Anda akan mendapatkannyaTypeError: Cannot read property 'toDate' of undefined
Jadi jika Anda memiliki pengguna dalam koleksi Anda yang tidak memiliki
createdAt
properti yang ditentukan. Anda harus menerapkan logika untuk memeriksa apakah pengguna memilikicreatedAt
properti sebelum mendapatkannya. Anda dapat melakukan sesuatu seperti ini:sumber
Saya pernah mengalami masalah di masa lalu dengan properti objek bersarang tidak merender dengan benar dalam daftar
item.someProp
yang dianggap objek, tetapiitem.someProp.someSubProp
tidak akan diselesaikan dengan nilaisomeSubProp
initem.someProp
.Jadi untuk mengatasi masalah ini, mengapa tidak mengevaluasi Timestamp ke objek tanggal polos (atau format tampilan yang diinginkan) saat membuat objek pengguna?
sumber
DocumentSnapshot#data()
danDocumentSnapshot#get()
menerima objek yang menentukan cara menanganiFieldValue.serverTimestamp()
nilai yang belum selesai . Secara default, yang belum selesai hanya akan menjadi nol. Menggunakan{ serverTimestamps: "estimate"}
akan mengubah nilai-nilai nol ini ke taksiran.