3

I am trying to figure out how to add timestamps to documents created in my firestore database.

I have read and tried each and every one of the suggestions in this post.

I have read the documentation links on that post and I can't make sense of the steps I'm supposed to try to implement in order to record the timestamp for the document creation date.

In my firebase settings I have:

firebase.initializeApp(config);
const database = firebase.database();
const fsDB = firebase.firestore();
const settings = { timestampsInSnapshots: true };


export { firebase, database as default, fsDB, settings };

I'm really not sure if the settings const is necessary because a lot of the posts on this point suggest that it is now some kind of default in firebase (I can't find the firebase documentation on that point).

Then, in my form, I have:

import * as firebase from '../../../firebase';
import { fsDB } from "../../../firebase";

I'm not sure why it's necessary to import these firebase files directly, because they are in the app entry point, but several posts have suggested it.

class Preregistration extends React.Component {
  constructor(props) {
    super(props);
    this.state = {selectedValue: null};
    this.state = {createdAt: firebase.database.serverTimestamp()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.createdAt.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
export default Preregistration;

I have also tried:

this.state = {createdAt: firebase.fsDB.serverTimestamp()};

this.state = {createdAt: firebase.firestore.FieldValue.serverTimestamp()};


this.state = {createdAt: firebase.FieldValue.serverTimestamp()};

None of these approaches work. There must be a simple way to add a time stamp to a document so that I can monitor when they were created. Why is it so difficult to figure out how to do it?

When I try:

this.state = {createdAt: firebase.fsDB.FieldValue.serverTimestamp()};

(note - my firestore is saved as fsDB),

I get an error that says:

TypeError: Cannot read property 'serverTimestamp' of undefined

I thought maybe (because of the way i define my config) the expression might be meant to read:

this.state = {createdAt: fsDB.FieldValue.serverTimestamp()};

but that produces the same error message

The firebase support ticket advice suggests:

createdAt: firebase.firestore.Timestamp.now(); 

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

TypeError: Cannot read property 'Timestamp' of undefined

It would be great to know how to use timestamps in firestore.

The firebase docs say:

var docRef = db.collection('objects').doc('some-id');

// Update the timestamp field with the value from the server
var updateTimestamp = docRef.update({
    timestamp: firebase.firestore.FieldValue.serverTimestamp()
});

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

TypeError: Cannot read property 'FieldValue' of undefined

I have tried each of these things setting both the initial value as well as a separate attempt at setState with a value. None of them work.

Taking Murray R's suggestion below, I tried both of these commented lines as shown and in {} and in (). None of these attempts work (the page won't render for the errors contained within them (failed to compile, expected ; are the error messages). I have sprinkled ; at every place I can think to put them but can't get this approach to work.

handleSubmit = (formState, { resetForm }) => {
    // Now, you're getting form state here!
    console.log("SUCCESS!! :-)\n\n", formState);
    fsDB
      .collection("contact")
      .add(formState)
      // .set createdAt: firebase.firestore.FieldValue.serverTimestamp()
      // .add createdAt: firebase.firestore.FieldValue.serverTimestamp()
      .then(docRef => {
        console.log("docRef>>>", docRef);
        this.setState({ selectedValue: null });
        resetForm(initialValues);
      })
      .catch(error => {
        console.error("Error adding document: ", error);
      });
  };
Mel
  • 2,481
  • 26
  • 113
  • 273

1 Answers1

4

To get the Firestore timestamp, firebase.firestore.FieldValue.serverTimestamp() is the correct call. Here's the catch: this method is only used within a DocumentReference .set() or .update() call (or, I believe, a CollectionReference .add()). For example, when adding a new document to your "contact" collection, you might combine formState with the new property 'createdAt' as you pass it to the .add() method:

handleFormSubmit(event) {
    // Now, you're getting form state here!
    console.log("SUCCESS!! :-)\n\n", formState);
    fsDB
      .collection("contact")
      .add({
        ...formState,
        createdAt: firebase.firestore.FieldValue.serverTimestamp()
      })
      .then(docRef => {
        console.log("docRef>>>", docRef);
        this.setState({ selectedValue: null });
        resetForm(initialValues);
      })
      .catch(error => {
        console.error("Error adding document: ", error);
      });
}
MurrayR
  • 426
  • 3
  • 6
  • Also bear in mind that when you retrieve that Firestore document, the createdAt property will be a _Firestore Timestamp_ object which you'll likely need to convert to a Javascript Date using the object's `.toDate()` method. – MurrayR May 13 '19 at 16:33
  • I tried this suggestion. It doesn't work. I have shown my attempt in the edited question above. Thanks anyway for trying to help. – Mel May 13 '19 at 21:30
  • 1
    Hi, I tried the updated suggestion. It throws this error: Unhandled Rejection (TypeError): Cannot read property 'FieldValue' of undefined – Mel May 13 '19 at 22:18
  • Then, when I try adding back (formState and {ResetForm} to the opening line and otherwise trying with your suggestion, I get an error that says: Uncaught (in promise) TypeError: _this.props.onSubmit is not a function – Mel May 13 '19 at 22:23
  • I have sent another support ticket to the people at firebase to try to get help to make timestamps work. I'll post the answer on this question when I find an answer. Thank you for trying to help. – Mel May 13 '19 at 22:24
  • I reviewed how you're importing your firebase references. You'll need to import 'firebase' itself to resolve the FieldValue undefined problem: `import { fsDB, firebase } from "../../../firebase";` This will give you access to `.FieldValue.serverTimestamp()`' – MurrayR May 13 '19 at 22:59
  • I have a separate line above (as shown at the top of my post that imports firebase). If i add it to the import statement you've shown, then I get an error saying firebase has already been declared. – Mel May 13 '19 at 23:07
  • Imports are currently: import firebase from '../../../firebase'; import { fsDB, settings } from "../../../firebase"; – Mel May 13 '19 at 23:08
  • Already, that doesn't make sense since they are imported at the app.js entry point, but they have both been imported since I started working on this problem. – Mel May 13 '19 at 23:08
  • I have tried substituting 'import firebase' with import * but that doesn't help either. – Mel May 13 '19 at 23:10
  • Just use a single import statement for your firebase stuff: `import { firebase, fsDB } from '../../../firebase';` (That's all that's needed for the samples you've shown. I can't know for sure that other firebase related imports aren't needed elsewhere in your code.) – MurrayR May 13 '19 at 23:13
  • I tried importing firestore (as well) in case you had a typo in your suggestion, but it doesn't help. I still get an error that says: Unhandled Rejection (TypeError): Cannot read property 'FieldValue' of undefined – Mel May 13 '19 at 23:14
  • Thank you. Moving them to the same line worked. Thank you! – Mel May 13 '19 at 23:15
  • i have to wait an hour to award the bounty – Mel May 13 '19 at 23:16