Home > Software engineering >  React nested map rendering multiple times
React nested map rendering multiple times

Time:01-06

I can't figure out why this is rendering multiple times. I need to map available times and booked times and then compare. When I compare, I need to exclude the times that have been booked from the available times. I can do the comparison ok but don't understand why it's outputting three times :(

An example.
Existing Bookings:
[startDateTime: 2023/05/06 09:00, endDateTime: 2023/05/06 10:30]
[startDateTime: 2023/05/06 10:30, endDateTime: 2023/05/06 12:00]
[startDateTime: 2023/05/06 12:00, endDateTime: 2023/05/06 13:30]

Available Times: [09:00, 09:15, 09:30, 09:45, 10:00, 10:15, 10:30, 10:45, 11:00, 11:15, 11:30, 11:45, 12:00, 12:15, 12:30, 12:45, 13:00, 13:15, 13:30, 13:45, 14:00, 14:15, 14:30, 14:45, 15:00]

So if the availableTime isSameOrAfter(startDateTime) or isSameOrBefore(endDateTime) all the times from 09:00 until 10:30 should be hidden and the next available time to display would be 10:45

`

<View>
                        <ScrollView horizontal style={{paddingTop: 20, paddingBottom: 25}}>
                            { existingBookings.map((existingBooking, key) => {
                                return <ListItem key={key}>
                                    { availableTimes.map((index, item) => {
                                        let exBookingStartTime = existingBooking.stDate;
                                        let exBookingEndTime = existingBooking.enDate;
                                        let newDummyDate = "2023-01-06 "   index;
                                        let dummyMomentTest = moment(newDummyDate, 'YYYY-MM-DD HH:mm').format('YYYY-MM-DD HH:mm');

                                        if(moment(dummyMomentTest).isSameOrAfter(exBookingStartTime) && moment(dummyMomentTest).isSameOrBefore(exBookingEndTime)) {
                                            return buildTimeScrollView(index, item, 'Booked');
                                        } else {
                                            return buildTimeScrollView(index, item, 'Available');
                                        }
                                    })}
                                </ListItem>
                            })}
                        </ScrollView>
                    </View>

The result I'm getting is partly correct. Though it is outputting three times like below because I have 3 existing booking records;

1st output
Booked Booked Booked Booked Booked Booked Booked Booked 10:45

2nd output which is added to the end of the first
09:00 09:15 09:30 09:45 10:00 10:15 10:30 Booked Booked Booked Booked Booked Booked Booked

3rd output which is added to the end of the second
09:00 09:15 09:30 09:45 10:00 10:15 10:30 10:45 11:00 11:15 11:30 11:45 Booked Booked Booked Booked Booked Booked Booked

Full Output ends up looking like this Booked Booked Booked Booked Booked Booked Booked Booked 09:00 09:15 09:30 09:45 10:00 10:15 10:30 Booked Booked Booked Booked Booked Booked Booked 09:00 09:15 09:30 09:45 10:00 10:15 10:30 10:45 11:00 11:15 11:30 11:45 Booked Booked Booked Booked Booked Booked Booked

Basically I just want to exclude the times in the existing bookings from the available times

CodePudding user response:

A possible solution

enter image description here

import * as React from 'react';
import {Text, View, ScrollView} from 'react-native';
import moment from 'moment';

const updateAvailableTimes = (
  bookings: Array<{stDate: string; enDate: string}>,
  availables: Array<string>,
  currDate: string,
) => {
  const newAvailables = [];
  for (const ava of availables) {
    const curr = moment(`${currDate} ${ava}`, 'YYYY-MM-DD hh:mm');
    let isBooked = false;
    for (const booking of bookings) {
      const st = moment(booking.stDate, 'YYYY-MM-DD hh:mm');
      const en = moment(booking.enDate, 'YYYY-MM-DD hh:mm');
      if (curr.isSameOrAfter(st) && curr.isSameOrBefore(en)) {
        newAvailables.push('Booked');
        isBooked = true;
        break;
      }
    }
    if (!isBooked) {
      newAvailables.push(ava);
    }
  }
  return newAvailables;
};

export default function Main() {
  const existingBookings = [
    {
      stDate: '2023-01-06 09:00',
      enDate: '2023-01-06 10:30',
    },
    {
      stDate: '2023-01-06 10:30',
      enDate: '2023-01-06 12:00',
    },
    {
      stDate: '2023-01-06 12:00',
      enDate: '2023-01-06 13:30',
    },
  ];

  const availableTimes = [
    '09:00',
    '09:15',
    '09:30',
    '09:45',
    '10:00',
    '10:15',
    '10:30',
    '10:45',
    '11:00',
    '11:15',
    '11:30',
    '11:45',
    '12:00',
    '12:15',
    '12:30',
    '12:45',
    '13:00',
    '13:15',
    '13:30',
    '13:45',
    '14:00',
    '14:15',
    '14:30',
    '14:45',
    '15:00',
  ];

  const currDate = '2023-01-06';

  return (
    <View
      style={{
        flex: 1,
        justifyContent: 'center',
      }}>
      <View style={{backgroundColor: 'lightgrey'}}>
        <ScrollView horizontal style={{paddingVertical: 20}}>
          {updateAvailableTimes(existingBookings, availableTimes, currDate).map(
            (val, idx) => {
              return (
                <View
                  key={idx}
                  style={{
                    marginHorizontal: 2,
                    borderWidth: 2,
                    borderColor: 'blue',
                    borderRadius: 10,
                    width: 80,
                    alignItems: 'center',
                  }}>
                  <Text>{val}</Text>
                </View>
              );
            },
          )}
        </ScrollView>
      </View>
    </View>
  );
}

The output from filtering out the unavailable times is ["Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "Booked", "13:45", "14:00", "14:15", "14:30", "14:45", "15:00"]

NOTE

The algorithm used in updateAvailableTimes is naïve and slow. If your bookings and availables arrays are fairly short (e.g., fewer than 100 each), the naïve algorithm should be fast enough. However, if their size can be big, you will have to optimize it (e.g., merge any overlapping bookings to reduce its size, binary search the available times against the bookings, etc.)

  • Related