Estou tentando descobrir como exibir um carimbo de data / hora do firestore em um aplicativo de reação.
Eu tenho um documento do firestore com um campo chamado createdAt.
Estou tentando incluí-lo em uma lista de saída (extraindo os bits relevantes aqui para que você não precise ler toda a lista de campos).
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()}
O único atributo que não será renderizado é a data.
Cada uma das tentativas acima gera um erro que diz:
TypeError: Não é possível ler a propriedade 'toDate' de undefined
Eu já vi esse post , e este post e este post , e este post e outros como eles, o que sugere que toDate () deve funcionar. Mas - esta extensão gera um erro para mim - inclusive quando tento a extensão toString.
Eu sei que ele sabe que há algo no firestore porque, quando tento user.createdAt, recebo um erro ao dizer que ele encontrou um objeto com segundos nele.
Tomando o exemplo de Waelmas abaixo, tentei registrar a saída do campo como:
this.db.collection('users').doc('HnH5TeCU1lUjeTqAYJ34ycjt78w22').get().then(function(doc) {
console.log(doc.data().createdAt.toDate());
}
Também tentei adicionar isso à minha declaração de mapa, mas obtive um erro que diz que user.get não é uma função.
{user.get().then(function(doc) {
console.log(doc.data().createdAt.toDate());}
)}
Ele gera a mesma mensagem de erro acima.
PRÓXIMA TENTATIVA
Uma coisa estranha que surgiu ao tentar encontrar uma maneira de registrar uma data no Firestore que me permita lê-la novamente é que, quando altero meu manipulador de envio de um formulário para usar esta formulação:
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();
};
Isso funciona para registrar uma data no banco de dados.
A forma da entrada do firestore é semelhante a esta:
Estou tentando exibir uma data neste componente:
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);
Quando tento lê-lo novamente - usando:
{item.email}
A mensagem de erro diz:
Erro: Os objetos não são válidos como um filho do React (encontrado: Registro de data e hora (segundos = 1576363035, nanossegundos = 52000000)). Se você pretendia render uma coleção de filhos, use uma matriz. no item (em UserIndex.jsx: 74)
Quando tento usar cada uma dessas tentativas:
{item.createdAt}
{item.createdAt.toDate()}
{item.createdAt.toDate().toISOString()}
Eu recebo um erro que diz:
TypeError: Não é possível ler a propriedade 'toDate' de undefined
Com base na capacidade de ler novamente as entradas registradas no mesmo documento em outros campos, espero que alguma delas funcione para produzir saída, mesmo que não esteja formatada da maneira que desejo. Isso não acontece.
PRÓXIMA TENTATIVA
Tomando o exemplo de Waelmas, tentei seguir as instruções, mas onde não estamos obtendo a mesma resposta está no primeiro passo. Onde Walemas obtém uma saída com base na extensão .toDate (), recebo um erro dizendo que toDate () não é uma função.
Consistente com a documentação do Firebase, tentei:
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());
}}))
Isso produz uma série de erros com a sintaxe e não consigo encontrar uma maneira de contorná-los.
PRÓXIMA TENTATIVA
Tentei criar um novo formulário para ver se eu poderia explorar isso sem o aspecto de autenticação do formulário de usuários.
Eu tenho um formulário que recebe entrada como:
this.props.firebase.db.collection("insights").add({
title: title,
text: text,
// createdAt1: new Date(),
createdAt: this.props.firebase.fieldValue.serverTimestamp()
})
Onde no formulário anterior, a nova tentativa Date () trabalhou para registrar uma data no banco de dados; neste exemplo, os dois campos para createdAt e createdAt1 geram a mesma entrada do banco de dados:
<div>{item.createdAt.toDate()}</div>
<div>{item.createdAt.toDate()}</div>
Quando tento gerar o valor das datas, a primeira gera um erro que diz:
Os objetos não são válidos como um filho do React (encontrado: dom 15/12/2019 21:33:32 GMT + 1100 (horário de verão do leste da Austrália)). Se você pretendia render uma coleção de filhos, use uma matriz
O segundo gera o erro dizendo:
TypeError: Não é possível ler a propriedade 'toDate' de undefined
Estou preso a idéias sobre o que tentar a seguir.
Vi este post que sugere que o seguinte pode fazer algo útil:
{item.createdAt1.Date.valueOf()}
Não faz. Ele gera um erro que diz:
TypeError: Não é possível ler a propriedade 'Date' de undefined
Esta postagem parece estar tendo o mesmo problema que eu, mas não explica como eles conseguiram exibir o valor da data que armazenaram.
Esta postagem parece estar travando na mensagem de erro da matriz, mas parece ter descoberto como exibir uma data usando createdAt.toDate ()