1

I've looked at some similar question and tried to change the code but the data still won't show. I've watch a few tutorials and I've got this far. This is my code.

 export default class HomeScreen extends React.Component {

  state = {
    dateItems: [],
    loading: false,
  }

  unsubscribe = null;

  async getAppointment() {
    const dateList = [];
    var snapshot = await firebase.firestore()
      .collection('appointment')
      .orderBy('createdAt', 'desc')
      .get()

    snapshot.docs.forEach(doc => {
      dateList.push({
        key: doc.id,
        date: doc.data().date,
        createdAt: doc.data().createdAt,
      });
      this.setState({
        dateItems: dateList,
        loading: false,
      });
    });
    console.log(dateList);
  }

  componentDidMount() {
    this.getAppointment();
  }

  render() {
    return (
      <View style={styles.container}>

        <View >
          <View style={styles.header}>
            <Text style={styles.headerTitle}>Appointments</Text>
            <Button
              onPress={() => this.props.navigation.navigate('Booking')} title="Add"
            />
          </View>
          <FlatList
            data={this.state.dateItems}
            renderItem={(item, index) => (
              <View>
                <Text style={styles.item}>{item.date}</Text>
                <Text>Created: {item.createdAt}</Text>
                <View style={styles.hr}></View>
              </View>
            )}
            keyExtractor={item => item.id}
          />
        </View>
      </View>
    );
  }
}

The data shows in an array in the console

Array [
  Object {
    "createdAt": t {
      "nanoseconds": 467000000,
      "seconds": 1591023433,
    },
    "date": t {
      "nanoseconds": 478000000,
      "seconds": 1592740813,
    },
    "key": "Qlaq8Nd5GYaxFYr9M6Iq",
  },
  Object {
    "createdAt": t {
      "nanoseconds": 31000000,
      "seconds": 1591020391,
    },
    "date": t {
      "nanoseconds": 859000000,
      "seconds": 1593327612,
    },
    "key": "ZsP2pBcNNgb4Nj6Jrpce",
  },
]

I need to show the date and not the timestamp for both date and createdAt. i don't know where I can implement this.

B_M
  • 91
  • 8
  • I think, you are getting issue here `snapshot.docs.forEach(doc => { dateList.push({ key: doc.id, date: doc.data().date, createdAt: doc.data().createdAt, });` try adding toJSON() to each line. – Shahanshah Alam Jun 01 '20 at 22:20
  • I get a `ReferenceError: toJSON is not defined` or `TypeError: doc.data(...).date.toJSON is not a function` – B_M Jun 02 '20 at 10:26

1 Answers1

1

Formatting dates in Javascript can be very messy since you get into all sorts of complications with timezones, etc.

But in general, to start with, you'll want a new Date object. To get that, you would do:

const date = new Date(doc.data().date.seconds * 1000)

This is because the Date constructor takes (as one option) the number of milliseconds since 1970 as its argument.

However, this will only give you a Date object, and console.log will return a very long string like "Mon Jun 01 2020 07:57:13 GMT-0700 (Mountain Standard Time)". To format it, you want Intl.DateTimeFormat:

const dateObj = new Date(doc.data().date.seconds * 1000)
const date = new Intl.DateTimeFormat('en-US').format(dateObj) // "6/1/2020"

If you want to have more granular control than that over the date format, look at this SO answer or, to make your life much easier, use something like Moment.js.

If you're ok with the default en-US formatting (or any other locale), your code will end up looking something like the following. I'm not sure why you are calling setState inside every loop of the forEach statement, but assuming you can save that until dateList is fully built, you can use map instead, which is more efficient:

const dateFormat = new Intl.DateTimeFormat('en-US') 
const dateList = snapshot.docs.map(doc => {
  const dateObj = new Date(doc.data().date.seconds * 1000)
  const createdAtObj = new Date(doc.data().createdAt.seconds * 1000)
  return {
    key: doc.id,
    date: dateFormat.format(dateObj),
    createdAt: dateFormat.format(createdAtObj)
  }
 });

 this.setState({
    dateItems: dateList,
    loading: false,
 })
jdaz
  • 4,794
  • 2
  • 16
  • 27
  • I tried your code, the only change in the console `Object { "createdAt": "5/29/2020", "date": "12/10/1815", "key": "0kGa3D7zpDmdP43q5RAy", },`. The data is still not showing on the screen. – B_M Jun 02 '20 at 10:50
  • You just need braces `{}` inside your `renderItem` function call, then you should be good: `renderItem={({item, index}) ...` – jdaz Jun 02 '20 at 13:52
  • The data shows, and there's a warning: `Warning: Each child in a list should have a unique "key" prop.` – B_M Jun 02 '20 at 14:35
  • One more thing, how can I specify to only show data made by the current user? – B_M Jun 02 '20 at 15:22
  • 1
    That completely depends on how you’ve set up your accounts and how the data is formatted. If every element of `snapshot.docs` has a `user` field, you can do something like `datelist = snapshot.docs.filter((doc) => (doc.user == currentUser)).map((doc) => ...` You should post a separate question if you can’t figure it out after messing around with it. – jdaz Jun 02 '20 at 16:12