J'essaie de comprendre comment afficher un horodatage Firestore dans une application React.
J'ai un document Firestore avec un champ nommé createdAt.
J'essaie de l'inclure dans une liste de sortie (en extrayant les bits pertinents ici afin que vous n'ayez pas à lire toute la liste des champs).
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()}
Le seul attribut qui ne sera pas rendu est la date.
Chacune des tentatives ci-dessus génère une erreur qui dit:
TypeError: Impossible de lire la propriété 'toDate' de indéfini
J'ai vu ce post , et ce post et ce post , et ce post et d'autres comme eux, qui suggèrent que toDate () devrait fonctionner. Mais - cette extension génère une erreur pour moi - y compris lorsque j'essaye l'extension toString.
Je sais qu'il sait qu'il y a quelque chose dans firestore parce que lorsque j'essaye user.createdAt, j'obtiens une erreur disant qu'il a trouvé un objet avec des secondes dedans.
En prenant l'exemple de Waelmas ci-dessous, j'ai essayé de consigner la sortie du champ comme suit:
this.db.collection('users').doc('HnH5TeCU1lUjeTqAYJ34ycjt78w22').get().then(function(doc) {
console.log(doc.data().createdAt.toDate());
}
J'ai également essayé d'ajouter cela à ma déclaration de carte, mais j'obtiens une erreur indiquant que user.get n'est pas une fonction.
{user.get().then(function(doc) {
console.log(doc.data().createdAt.toDate());}
)}
Il génère le même message d'erreur que ci-dessus.
PROCHAINE TENTATIVE
Une chose étrange qui est survenue en essayant de trouver un moyen d'enregistrer une date dans Firestore qui me permet de la relire ensuite, c'est que lorsque je change de gestionnaire de soumission sous une forme pour utiliser cette formulation:
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();
};
Cela fonctionne pour enregistrer une date dans la base de données.
La forme de l'entrée Firestore ressemble à ceci:
J'essaie d'afficher une date dans ce composant:
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);
Quand j'essaye de le relire - en utilisant:
{item.email}
Le message d'erreur se lit comme suit:
Erreur: les objets ne sont pas valides en tant qu'enfant React (trouvé: horodatage (secondes = 1576363035, nanosecondes = 52000000)). Si vous vouliez rendre une collection d'enfants, utilisez plutôt un tableau. dans l'élément (à UserIndex.jsx: 74)
Lorsque j'essaie d'utiliser chacune de ces tentatives:
{item.createdAt}
{item.createdAt.toDate()}
{item.createdAt.toDate().toISOString()}
Je reçois une erreur qui dit:
TypeError: Impossible de lire la propriété 'toDate' de indéfini
Sur la base de la possibilité de relire les entrées enregistrées dans le même document dans d'autres champs, je m'attends à ce que l'une d'entre elles fonctionne pour produire une sortie, même si elle n'est pas formatée comme je le souhaite. Cela n'arrive pas.
PROCHAINE TENTATIVE
En prenant l'exemple de Waelmas, j'ai essayé de suivre les instructions, mais là où nous n'obtenons pas la même réponse, c'est dans la première étape. Lorsque Walemas obtient une sortie basée sur l'extension .toDate (), j'obtiens une erreur disant que toDate () n'est pas une fonction.
Conformément à la documentation de Firebase, j'ai essayé:
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());
}})
Cela produit une chaîne d'erreurs avec la syntaxe et je ne peux pas trouver un moyen de les contourner.
PROCHAINE TENTATIVE
J'ai ensuite essayé de créer un nouveau formulaire pour voir si je pouvais l'explorer sans l'aspect authentification du formulaire utilisateurs.
J'ai un formulaire qui prend en entrée:
this.props.firebase.db.collection("insights").add({
title: title,
text: text,
// createdAt1: new Date(),
createdAt: this.props.firebase.fieldValue.serverTimestamp()
})
Dans le formulaire précédent, la nouvelle tentative Date () a fonctionné pour enregistrer une date dans la base de données, dans cet exemple, les deux champs pour createdAt et createdAt1 génèrent la même entrée de base de données:
<div>{item.createdAt.toDate()}</div>
<div>{item.createdAt.toDate()}</div>
Lorsque j'essaie de sortir la valeur des dates, la première génère une erreur qui dit:
Les objets ne sont pas valides en tant qu'enfant React (trouvé: dim. 15 déc.2019 21:33:32 GMT + 1100 (Australian Eastern Daylight Time)). Si vous vouliez rendre une collection d'enfants, utilisez plutôt un tableau
Le second génère l'erreur en disant:
TypeError: Impossible de lire la propriété 'toDate' de indéfini
Je suis coincé pour des idées sur quoi essayer ensuite.
J'ai vu ce post qui suggère que ce qui suit pourrait faire quelque chose d'utile:
{item.createdAt1.Date.valueOf()}
Ce n'est pas le cas. Il rend une erreur qui dit:
TypeError: Impossible de lire la propriété 'Date' de non défini
Ce message semble avoir le même problème que moi, mais n'entre pas dans la façon dont ils ont réussi à afficher la valeur de date qu'ils ont stockée.
Ce message semble être bloqué sur le message d'erreur du tableau, mais semble avoir trouvé comment afficher une date à l'aide de createdAt.toDate ()