0

I'm adding a document to a firestore collection (inboxItems) onSubmit of a form.

onCreateInboxItem = event => {
  this.props.firebase.inboxItems().add({
    name: this.state.newInboxItemName,
    created: '', // I need a timestamp field here
  })
  this.setState({ name: '' });
  event.preventDefault();
}

How do I get the created field to be a timestamp field, with current timestamp as a value? It would need to be consistent across users and timezones.

I see firebase.firestore.FieldValue.serverTimestamp() mentioned in the firebase docs, but at this point the field value isn't set yet. I would like to avoid an extra operation to update the field.

Pim
  • 445
  • 1
  • 8
  • 24
  • It's not clear to me why you can't use FieldValue.serverTimestamp(). You just use it as the value of a field at the time you call add(). – Doug Stevenson Apr 18 '19 at 21:04
  • "this.props.firebase.firestore.FieldValue.serverTimestamp()" doesn't seem to work. Perhaps I'm referencing something wrong here, but I thought FieldValue is only accessible when the field is already set. – Pim Apr 18 '19 at 21:08

2 Answers2

1

You can do:

created: new Date(),

or:

created: firebase.firestore.Timestamp.fromDate(new Date()),

Alternatively you could use a cloud function, as described here, though that might be overkill.

Colin Ricardo
  • 16,488
  • 11
  • 47
  • 80
  • Yes, but doesn't that create a timestamp based on the local machine time? I would need to make sure it's consistent across users and timezones. – Pim Apr 18 '19 at 20:54
  • I believe this still would create a local timestamp, the function seems to just convert your local timestamp to a firebase timestamp. I see something in the docs like "firebase.firestore.FieldValue.serverTimestamp()", but at this point the field value isn't set yet. – Pim Apr 18 '19 at 21:00
  • You should be able to use `set()` in place of `update()` in the example you're talking about. – Colin Ricardo Apr 18 '19 at 21:03
0

Since I use firebase authentication, I initialize firebase with the root App component via the context API. I managed to solve it by adding a helper in my Firebase settings file:

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

    /* Helper */

    this.fieldValue = app.firestore.FieldValue;

    /* Firebase API's */

    this.db = app.firestore();
  }
}

And then:

this.props.firebase.inboxItems().add({
  created: this.props.firebase.fieldValue.serverTimestamp(),
  name: this.state.newInboxItemName,
})
Pim
  • 445
  • 1
  • 8
  • 24
  • Typically you just make `app` available to your entire app so you don't have to pick the parts out of it that you need. Most JavaScript just assumes that it's a global called `firebase`. – Doug Stevenson Apr 18 '19 at 21:27
  • I use the React Context API so I can provide one instance of firebase at the root component level (needed for authentication, more efficient, and less error-prone). This means that firebase is passed as a prop to child components, that's why the helper is needed. – Pim Apr 18 '19 at 21:36
  • @DougStevenson There's a really neat example on https://www.robinwieruch.de/complete-firebase-authentication-react-tutorial/, I believe it's the more solid way to use firebase in react. – Pim Apr 18 '19 at 21:43