Firebase:如何在Firestore中向数据库添加时间戳-使用React Context API [英] Firebase: how to add timestamp to database in firestore - where react context api is used

查看:121
本文介绍了Firebase:如何在Firestore中向数据库添加时间戳-使用React Context API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的React应用程序的Firebase表单数据中添加时间戳.

I am trying to add a time stamp to my firebase form data in my react app.

应用程序使用react上下文api将应用程序包装在FirebaseContext.Provider中,如下所示:

The app uses react context api to wrap the app in a FirebaseContext.Provider as follows:

ReactDOM.render(

  <FirebaseContext.Provider value={new Firebase()}>
    <App />

  </FirebaseContext.Provider>,
  document.getElementById('root'),
);

上下文提供者具有:

import React from 'react';
const FirebaseContext = React.createContext(null);
export const withFirebase = Component => props => (
  <FirebaseContext.Consumer>
    {firebase => <Component {...props} firebase={firebase} />}
  </FirebaseContext.Consumer>
);
export default FirebaseContext;

然后,需要firebase的每个组件都包装在使用者中,如下所示:

Then, each component that needs firebase is wrapped in the consumer, as follows:

import Firebase, { withFirebase } from "../../firebase"

export default withFirebase(Register)

在我的提交处理程序中,我正在尝试向表单数据添加时间戳:

In my submit handler, I'm trying to add a timestamp to the form data:

handleCreate = () => {

    const { form } = this.formRef.props;
    form.validateFields((err, values) => {
      if (err) {
        return;
      }
      // console.log("does it know what firebase is?", this.props.firebase.db);
    //   console.log("try time", this.props.firebase.db.FieldValue.serverTimestamp());
      console.log("it can get this far");
      console.log(this.props.firebase.firestore.FieldValue.serverTimestamp());
      console.log("it can get this far 2");

      const payload = {
        ...values,
        // role: formState.role.value,
        // created: this.props.firebase.fieldValue.serverTimestamp(),
        //  console.log("try to get a timestamp to work", this.props.firebase.serverValue.TIMESTAMP),
        // console.log("it can get to payload"),

        // createdAt: this.props.firebase.serverValue.TIMESTAMP
        // createdAt: this.props.firebase.FieldValue.serverTimestamp

        // createdAt: this.props.firebase.firestore.FieldValue.serverTimestamp(),
      }
      // console.log("formvalues", payload);


      // console.log('Received values of form: ', values);
      this.props.firebase.db
          .collection("preregistrations")
          .add(payload)
          // .set(FieldValue.serverTimestamp())

          // .add (createdAt: this.props.firebase.firestore.FieldValue.serverTimestamp());

          // .add(
          //   createdAt: this.props.firebase.firestore.FieldValue.serverTimestamp()
          // )

          // .then(docRef => {
            // resetForm(initialValues);

          // })
          .then(e => this.setState({ modalShow: true }))
          .catch(error => {
            console.error("Error adding document: ", error);
          });

      form.resetFields();
      this.setState({ visible: false });
    });

};

我的firebase配置如下设置.

My firebase config is setup as follows.

import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import firestore from "firebase/firestore";


class Firebase {
  constructor() {
    app.initializeApp(config).firestore();
    this.auth = app.auth();
    // this.db = app.firebase.database()
    this.db = app.firestore();

  }  

以前,这种方法有效:

createdAt: this.props.firebase.firestore.FieldValue.serverTimestamp()

firebase文档表示FieldValue可与一起使用.设置和.update.在我尝试的那些尝试包括"FieldValue"步骤的地方,我正在尝试将其与.add

The firebase documents say that FieldValue works with .set and .update. Where those of the attempts I'm making include the "FieldValue" step, I'm trying to use it with .add

时间戳文档使用此格式来提供时间戳:

The timestamp documentation uses this format to give a timestamp:

firebase. firestore.Timestamp

我尝试将这种格式作为有效负载中的行项目使用,以及将数据发送到数据库的步骤:

I've tried following this format as a line item in the payload as well as a step in sending data to the database:

createdAt: this.props.firebase.firestore.Timestamp,

这篇文章中列出了以前可行的另一种方法.答案和firebase文档建议时间戳仅适用于.set和.update,而我正尝试将其与.add一起使用.Firebase可能发生了某些变化,因此它不再可与.add一起使用-但我尝试在.add步骤之后添加.set步骤,但也无济于事.

Another approach that has previously worked is set out in this post. The answer and the firebase documents suggest that the timestamps only work with .set and .update, whereas I'm trying to use it with .add. Perhaps something has changed in firebase so the it no longer works with .add - but I tried adding a .set step after my .add step and that didn't work either.

this.props.firebase.db
          .collection("preregistrations")
          .add(payload)
          .set(FieldValue.serverTimestamp())

我有一个建议使用此方法的教程.

I have a tutorial that recommends using this approach.

console.log("try timestamp",  this.props.firebase.serverValue.TIMESTAMP),

它不起作用.没有错误消息生成并且控制台日志不运行-表单只是挂起并且不提交.

It doesn't work. No error message gets generated and the console log does not run -the form just hangs and does not submit.

本教程随附一本书,指导该教程从实时数据库转移到Firestore.关于时间戳的唯一说明是:

This tutorial comes with a book that directs to this tutorial for moving from realtime database to firestore. The only remark it makes about using timestamps is to say:

使用时间戳的设置,在本例中为createdData我们邮件实体的属性也进行了一些更改.

The set up for using timestamps, in this case for the createdData property for our message entities, has also changed slightly.

它没有透露轻微变化是什么-但它确实提供了2条线索.

It does not disclose what the slight change is - but it does give 2 clues.

首先-有一个

First - there is a repo linked to the post which has a timestamp in it like so:

  createdAt: this.props.firebase.fieldValue.serverTimestamp().

这与先前在表单提交处理程序中进行的尝试相同.

This is the same as the attempt previously made in the form submit handler.

第二个-该帖子参考了 firestore文档的这一部分,以了解如何确定从实时数据库更改为Firestore.该文档的一点内容都没有关于在Firestore中创建时间戳的任何内容.该文档确实有一个 FriendlyEats 的示例应用程序,该应用程序的代码带有带有时间戳的表.它具有:

Second - the post references this bit of the firestore documentation for how to figure out changing from realtime database to firestore. That bit of the documentation doesn't have anything to say about making a timestamp in firestore. The documentation does have an example application for FriendlyEats which has code with a table with a timestamp. It has:

 rating.timestamp = new Date();

它也引用了一些从快照中删除时间戳的内容,但是在更新示例以删除它们之前,我找不到代码,因此我可以找到添加方法.

It also has references to something removing timestamps from snapshots but I can't find the code before the example was updated to remove them so that I can find out how to add them.

这篇文章建议有必要将*作为Firebase导入以获得时间戳工作.如果导入该内容,则会收到警告,提示不要在开发中使用*.这是否意味着除了我在firebase配置中导入的软件包(如下所示)以外,还有一个单独的软件包才能使时间戳生效-如果存在-它是否具有特定名称-还是*导入必需获得时间戳记来工作?

This post suggests that it is necessary to import * as firebase to get the timestamps to work. If I import that, then I get a warning saying not to use the * except in development. Does this mean there is a separate package other than the ones I have imported in my firebase config (as below) that is needed to make timestamps work - and if there is - does it have a specific name - or is the * import necessary to get timestamps to work?

import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import firestore from "firebase/firestore";

我尝试遵循该帖子中的方法,并且:

I tried following the approach in that post and:

  1. 在表格文件中导入*:

  1. imported * in the form file:

从"firebase"导入*作为firebase;

import * as firebase from 'firebase';

在有效负载中添加了以下内容:

added the following to the payload:

createdAt:this.props.firebase.db.Timestamp,

createdAt: this.props.firebase.db.Timestamp,

这行不通-没有错误消息-但到达该步骤时表单将挂起.

It doesn't work - no error messages - but the form hangs when it gets to that step.

下次尝试

下一步,我尝试使用:

createdAt: this.props.firebase.fieldValue.serverTimestamp(),

这是因为本教程(大致指的是更改,要求使用带Firestore的日期包含指向

This is because this tutorial (which loosely refers to changes requires to use dates with firestore includes a link to a repo that uses this format).

然后在firebase.js中,我有一个助手:

Then in firebase.js I have a helper as:

class Firebase {
  constructor() {
    app.initializeApp(config).firestore();


    /* Firebase APIs */
    this.auth = app.auth();
    this.db = app.firestore();

    /* helpers */
    this.fieldValue = app.firestore.FieldValue;

请注意,在助手中,FieldValue是Field的大写字母.

Note that in the helper, FieldValue is upper case for Field.

尝试此操作时,出现错误消息:

When I try this, I get an error that says:

FirebaseError:函数DocumentReference.set()调用无效数据.不支持的字段值:未定义(可在字段createdAt中找到)

FirebaseError: Function DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field createdAt)

当我尝试使createdAt在时间戳创建者中使用类似的大小写时(

When I try making the createdAt use similar casing in the timestamp creator (which the answer to this post suggests is correct), I try:

createdAt: this.props.firebase.FieldValue.serverTimestamp(),

这也失败.没有错误消息,但表单未提交.

This also fails. No error message but the form does not submit.

下次尝试

当我将createdAt步骤从有效负载中移出,并在数据库中创建用户时尝试在Submit handler步骤中使用,就像这样:

When I move the createdAt step out of the payload and just try to use in the submit handler step when the user is created in the database, like so:

TypeError:无法读取未定义的属性"serverTimestamp"

TypeError: Cannot read property 'serverTimestamp' of undefined

return this.props.firebase.user(authUser.user.uid).set(
            {
              name: values.name,
              email: values.email,
              // createdAt: values.createdAt,
              createdAt: this.props.firebase.FieldValue.serverTimestamp(),

            },
            { merge: true }
          );
        })

firebase会忽略用户设置的步骤(它不会创建记录).控制台错误说:

the user set step is ignored by firebase (it does not create the record). The console error says:

TypeError: Cannot read property 'serverTimestamp' of undefined

推荐答案

为希望为您提供服务器时间戳的帮助,我修改了简单的react-firebase-hook应用程序,以解决该问题:https://stackoverflow.com/a/60504303/610053

To hopefully help you with server timestamp I have modified the simple react-firebase-hook app created as an answer for this question: https://stackoverflow.com/a/60504303/610053

  1. 我已经使用名为serverTimestamp的额外方法更新了Firebase类:

class Firebase {
    constructor() {
        app.initializeApp(firebaseConfig);

        this.realtimedb = app.database();
        this.firestore = app.firestore();

        this.serverTimestamp = app.firestore.FieldValue.serverTimestamp;
    }
}

const FirebaseContext = React.createContext(null);

const App = () => {
    const firebase = React.useContext(FirebaseContext);
    const [counter, setCounter] = React.useState(-1);
    const [timestamp, setTimestamp] = React.useState(null);

    React.useEffect(() => {
        const unsubscribe = firebase.firestore.collection("counters").doc("simple").onSnapshot(documentSnapshot => {
            if(documentSnapshot) {
                const data = documentSnapshot.data();
                console.log("New data", data);
                setCounter(data.value);

                if(data.updatedAt) {
                    let initDate = new Date(0);
                    initDate.setSeconds(data.updatedAt.seconds);
                    setTimestamp(initDate);
                }
            }
        })

        return () => unsubscribe;
    }, []);

    const handleIncrement = () => {
        firebase.firestore.collection("counters").doc("simple").update({
            value: counter + 1,
            updatedAt: firebase.serverTimestamp(),
        });
    }

    return (<div>
        <div>
            Current counter value: {counter}. Updated: { timestamp ? timestamp.toString() : "Never?.." }
        </div>
        <div>
            <button onClick={handleIncrement}>Increment</button>
        </div>
    </div>);
};

这篇关于Firebase:如何在Firestore中向数据库添加时间戳-使用React Context API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆