Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
220 views
in Technique[技术] by (71.8m points)

javascript - React - display a firestore timestamp

I am trying to figure out how to display a firestore timestamp in a react app.

I have a firestore document with a field named createdAt.

I am trying to include it in a list of output (extracting the relevant bits here so that you don't have to read through the entire list of fields).

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()}

The only attribute that won't render is the date.

Each of the above attempts generates an error that says:

TypeError: Cannot read property 'toDate' of undefined

I have seen this post, and this post and this post, and this post and others like them, which suggest that toDate() should work. But - this extension throws an error for me - including when I try the toString extension.

I know it knows there is something in firestore because when I try user.createdAt, I get an error saying it found an object with seconds in it.

Taking the example from Waelmas below, I tried to log the output of the field as:

this.db.collection('users').doc('HnH5TeCU1lUjeTqAYJ34ycjt78w22').get().then(function(doc) {
  console.log(doc.data().createdAt.toDate());

}

I also tried adding this to my map statement but get an error that says user.get is not a function.

{user.get().then(function(doc) {
                    console.log(doc.data().createdAt.toDate());}
                  )}

It generates the same error message as above.

enter image description here

NEXT ATTEMPT

One strange thing that has come up in trying to find a way to record a date in Firestore that allows me to then read it back, is that when I change my submit handler in one form to use this formulation:

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();
    };

That works to record a date in the database.

The form of the firestore entry looks like this:

enter image description here

I'm trying to display a date in this component:

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);

When I try to read it back - using:

{item.email}

The error message reads:

Error: Objects are not valid as a React child (found: Timestamp(seconds=1576363035, nanoseconds=52000000)). If you meant to render a collection of children, use an array instead. in Item (at UserIndex.jsx:74)

When I try using each of these attempts:

{item.createdAt}
{item.createdAt.toDate()}
{item.createdAt.toDate().toISOString()}

I get an error that says:

TypeError: Cannot read property 'toDate' of undefined

Based on the ability to read back entries logged in the same document in other fields, I'm expecting any of these to work to produce output -even if it's not formatted in the way I want. That doesn't happen.

NEXT ATTEMPT

Taking Waelmas' example, I tried to follow the instructions, but where we aren't getting the same response is in the first step. Where Walemas gets an output based on the .toDate() extension, I get an error saying toDate() is not a function.

Consistent with the Firebase documentation, I tried:

    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());

} })

This produces a string of errors with the syntax and I can't find a way around them.

NEXT ATTEMPT

I then tried making a new form to see if I could explore this without the authentication aspect of the users form.

I have a form that takes input as:

this.props.firebase.db.collection("insights").add({
            title: title,
            text: text,
            // createdAt1: new Date(),
            createdAt: this.props.firebase.fieldValue.serverTimestamp()
        })

Where in the previous form, the new Date() attempt worked to record a date in the database, in this example both fields for createdAt and createdAt1 generate the same database entry:

enter image description here

<div>{item.createdAt.toDate()}</div>
                    <div>{item.createdAt.toDate()}</div>

When I try to output the value of the dates, the first one generates an error that says:

Objects are not valid as a React child (found: Sun Dec 15 2019 21:33:32 GMT+1100 (Australian Eastern Daylight Time)). If you meant to render a collection of children, use an array instead

The second generates the error saying:

TypeError: Cannot read property 'toDate' of undefined

I'm stuck for ideas on what to try next.

I saw this post that suggests that the following might do something useful:

                {item.createdAt1.Date.valueOf()}

It doesn't. It renders an error that says:

TypeError: Cannot read property 'Date' of undefined

This post seems to be having the same trouble as me, but doesn't go into how they managed to display the date value they stored.

This post seems to be getting stuck at the array error message, but seems to have figured out how to display a date using createdAt.toDate()

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...