Reactjs Firebase:如何向firestore中的数据库添加时间戳-使用react上下文api的地方

Reactjs Firebase:如何向firestore中的数据库添加时间戳-使用react上下文api的地方,reactjs,firebase,google-cloud-firestore,Reactjs,Firebase,Google Cloud Firestore,我正在尝试在react应用程序中向firebase表单数据添加时间戳 应用程序使用react-context api将应用程序包装在FirebaseContext中。提供程序如下: ReactDOM.render( <FirebaseContext.Provider value={new Firebase()}> <App /> </FirebaseContext.Provider>, document.getElementById('

我正在尝试在react应用程序中向firebase表单数据添加时间戳

应用程序使用react-context api将应用程序包装在FirebaseContext中。提供程序如下:

ReactDOM.render(

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

  </FirebaseContext.Provider>,
  document.getElementById('root'),
);
import Firebase, { withFirebase } from "../../firebase"

export default withFirebase(Register)
在我的提交处理程序中,我试图向表单数据添加时间戳:

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配置设置如下

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()
假设FieldValue与.set和.update一起工作。我正在尝试的那些步骤包括FieldValue步骤,我正在尝试将其与.add一起使用

使用此格式提供时间戳:

firebase. firestore.Timestamp
我尝试将此格式作为有效负载中的行项目以及向数据库发送数据的步骤:

createdAt: this.props.firebase.firestore.Timestamp,
另一种以前行之有效的方法载于。答案和firebase文档表明时间戳只适用于.set和.update,而我尝试将其用于.add。也许firebase中发生了一些变化,因此它不再与.add一起工作-但我尝试在.add步骤之后添加.set步骤,但这也不起作用

this.props.firebase.db
          .collection("preregistrations")
          .add(payload)
          .set(FieldValue.serverTimestamp())
我有一个教程建议使用这种方法

console.log("try timestamp",  this.props.firebase.serverValue.TIMESTAMP),
它不起作用。没有生成错误消息,控制台日志也没有运行-表单只是挂起,没有提交

本教程附带一本书,介绍如何从实时数据库移动到firestore。关于使用时间戳,它唯一要说的是:

用于使用时间戳的设置,在本例中为createdData 消息实体的属性也略有更改

它没有透露细微的变化是什么——但它确实给出了两条线索

首先-有一个链接到贴子,其中有一个时间戳,如下所示:

  createdAt: this.props.firebase.fieldValue.serverTimestamp().
这与之前在表单提交处理程序中进行的尝试相同

第二,这篇文章引用了这一点,以了解如何从实时数据库更改为firestore。那个些文档并没有关于在firestore中创建时间戳的任何内容。文档中确实有一个示例应用程序,其代码带有带有时间戳的表。它有:

 rating.timestamp = new Date();
它还引用了从快照中删除时间戳的内容,但在更新示例以删除时间戳之前,我找不到代码,以便了解如何添加时间戳

建议有必要将*作为firebase导入,以使时间戳生效。如果我导入它,那么我会收到一条警告,说除了在开发中,不要使用*。这是否意味着除了我在firebase配置中导入的包之外,还有一个单独的包需要使时间戳工作?如果有,它是否有一个特定的名称?或者*导入是使时间戳工作所必需的

import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import firestore from "firebase/firestore";
我在那篇文章中尝试了以下方法:

在表单文件中导入*:

从“firebase”导入*作为firebase

将以下内容添加到有效负载:

createdAt:this.props.firebase.db.Timestamp

它不工作-没有错误消息-但是当到达该步骤时,表单将挂起

下一次尝试

接下来,我尝试使用:

createdAt: this.props.firebase.fieldValue.serverTimestamp(),
这是因为本教程松散地引用了更改,要求将日期与firestore一起使用,其中包含一个指向使用此格式的的的链接

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

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


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

    /* helpers */
    this.fieldValue = app.firestore.FieldValue;
请注意,在助手中,FieldValue是字段的大写字母

当我尝试此操作时,会出现一个错误,显示:

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

当我尝试使createdAt在timestamp creator中使用类似的大小写(其答案是正确的)时,我尝试:

createdAt: this.props.firebase.FieldValue.serverTimestamp(),
这也失败了。没有错误消息,但表单未提交

下一次尝试

当我将createdAt步骤移出负载,并在数据库中创建用户时尝试在提交处理程序步骤中使用时,如下所示:

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

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忽略了用户设置步骤,因为它不创建记录。控制台错误显示:

TypeError: Cannot read property 'serverTimestamp' of undefined

是的,*导入是使时间戳正常工作所必需的。您需要导入整个firebase包的时间戳,以及我认为新的数组增量功能

我敢肯定,这里的问题是,您将实际的firebase导入与配置文件中命名为firebase的类混淆了

在您引用的文件createdAt中:this.props.firebase.fieldValue.serverTimestamp。从“firebase”导入*作为“firebase”;然后将其更改为createdAt:_firebase.fieldValue.serverTimestamp

我使用了u,这样你就不会有命名冲突了


如果在尝试此操作时仍然出现错误,请在下面的评论中分享。

此操作无需从firebase导入*as firebase

createdAt: this.props.firebase.fieldValue.serverTimestamp()
我不懂
明白为什么这样做-它的格式与firebase文档中显示的格式不同,而且它看起来也不像我以前使用过的任何东西-但我现在不想问问题。我希望这对其他人有所帮助。

因此,事实证明,回购协议可以记录日期,但这仍然不是一个答案,因为它不允许显示该日期

当我删除关于如何制作时间戳的所有教程和firestore文档建议时,这一行用于创建此数据库条目:

如果要将其转换为ISOstring,也可以这样做:

      createdAt: new Date().ISOstring
下一步是找出如何读回它

如果其他人在思考如何记录时间戳时遇到困难,这里有一个示例。

您可以使用Firebase提供的时间戳

import * as firebase from 'firebase';

createdAt:firebase.database.ServerValue.TIMESTAMP

它将为您完成工作

希望能够帮助您获得服务器时间戳我修改了simple react firebase hook应用程序,该应用程序是为回答以下问题而创建的:

我已使用名为serverTimestamp的额外方法更新了Firebase类: 使用firestore很重要:

import * as firebase from 'firebase';

createdAt: firebase.firestore.FieldValue.serverTimestamp()

另一方面,我认为通过上下文传递firebase是完全没有意义的,因为您可以将它从配置文件导入到应用程序中需要的任何位置。使用上下文是一个完全不必要的复杂的附加层。对于这个多余的用例,您使用上下文有什么具体的原因吗?谢谢。我现在再试一次。是否每个人都忽略了不在开发环境之外导入*的错误?本教程建议上下文包装是一种功能改进。它给出了整个应用程序运行的原因,然后可以包装需要访问它的组件。然后,我的想法是,我可以使用角色和权限来指定条件。有没有一个惯例能更好地做到这一点?我试过了。它不起作用。它不会生成任何错误消息-表单只是挂起。我尝试了console.log\u firebase.fieldValue.serverTimestamp;在我定义有效载荷之后。前后都有日志。那个先跑然后停的,看起来你已经搞定了。不错。关于前一点,我的建议是只导入没有上下文的文件。我不确定它是否更好,它更简单。如果您需要传递“使用角色和权限指定条件”,则可以,但如果您不这样做,则越简单越好,尤其是在您尝试学习时。
import * as firebase from 'firebase';

createdAt:firebase.database.ServerValue.TIMESTAMP
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>);
};
import * as firebase from 'firebase';

createdAt: firebase.firestore.FieldValue.serverTimestamp()