P
P
ParaBellum5772021-07-15 12:19:04
React
ParaBellum577, 2021-07-15 12:19:04

How to optimize react-beautiful-dnd?

I have a calendar similar to Google's, in which events are created, rummaged around, while there is a drag and drop. I am using this lib .
The problem is that I have 500+ droppable elements on the page (these are days broken into 15 minute cells), and when I have a weekly view open, when dragging elements down or up, when the page scrolls, dnd decently slows down. There is no such thing in the daily view, because the number of cells is reduced by 7 times. Tell me, is it possible to somehow optimize the work of this lib?
Droppable component looks like this:

import React, { FC, memo, useState } from 'react';
import { getTimeWithTimeZone, timezone } from 'utils/helpers/momentTime';
import { Droppable } from 'react-beautiful-dnd';
import moment, { Moment } from 'moment';
import { IEvents } from 'types';
import _ from 'lodash';
import Modal from './modal';
import Event from './event';
import styles from './index.module.scss';

interface ITable {
  days: Moment[][];
  weekCount: number;
  daysToShow: number;
  addEvent: (data: IEvents, unitId: number) => void;
  editEvent: (unitId: number, eventId: number, data: IEvents) => void;
  deleteEvent: (unitId: number, eventId: number) => void;
  events: IEvents[];
  timeLine: string[];
}
const Table: FC<ITable> = ({
  days,
  weekCount,
  daysToShow,
  addEvent,
  events,
  timeLine,
  editEvent,
  deleteEvent,
}) => {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [selectedTimeStamp, setSelectedTimeStamp] = useState<string>(
    moment().format('LT')
  );
  const [selectedDay, setSelectedDay] = useState<moment.Moment>();
  const [editEventData, setEditEventData] = useState<IEvents>();

  const handleEdit = (eventData: IEvents) => {
    setEditEventData(eventData);
    setIsModalOpen(!isModalOpen);
  };

  const renderBlocks = (
    event: IEvents,
    idx: number,
    timeStamp: string,
    day: moment.Moment
  ) => {
    let render = null;
    const startTime = getTimeWithTimeZone(
      event.startTimeStr || '00:00',
      'HH:mm'
    );
    const eventTime = moment(
      `${moment(startTime, 'HH:mm').format('LT')} ${moment(day).format(
        'MMM, D'
      )}`
    );
    const position = moment(`${timeStamp} ${moment(day).format('MMM, D')}`);
    const diff = eventTime.diff(position, 'minutes');

    if (
      startTime === moment(timeStamp, 'LT').format('HH:mm') ||
      (diff <= 14 && diff > 0)
    ) {
      if (
        day.format('YYYY-MM-DD') ===
        moment(event.startTime)
          .utc()
          .add(timezone, 'minutes')
          .format('YYYY-MM-DD')
      ) {
        render = (
          <Event
            handleEdit={handleEdit}
            deleteEvent={deleteEvent}
            daysToShow={daysToShow}
            diff={diff}
            key={event.id}
            day={day}
            event={event}
            idx={idx}
          />
        );
      }
    }
    return render;
  };

  const handleOpen = (timeStamp: string, day: moment.Moment) => {
    setEditEventData(undefined);
    setSelectedTimeStamp(timeStamp);
    setSelectedDay(day);
    setIsModalOpen(!isModalOpen);
  };

  return (
    <div className={styles.days}>
      <Modal
        isModalOpen={isModalOpen}
        setIsModalOpen={setIsModalOpen}
        addEvent={addEvent}
        day={selectedDay}
        time={selectedTimeStamp}
        editEventData={editEventData}
        editEvent={editEvent}
        deleteEvent={deleteEvent}
      />
      {!_.isEmpty(days) &&
        !_.isEmpty(days[weekCount]) &&
        days[weekCount].map((day: moment.Moment) => (
          <div
            key={day.format('DD-MM-YYYY')}
            style={daysToShow === 1 ? { width: '100%' } : {}}
            className={styles.day}
          >
            {timeLine.map((timeStamp: string) => (
              <Droppable
                isDropDisabled
                droppableId={`${day}_${timeStamp}`}
                key={timeStamp}
              >
                {(provided, snapshot) => (
                  <div
                    {...provided.droppableProps}
                    ref={provided.innerRef}
                    className={styles.timeLine}
                    style={{
                      transition: 'all 0.1s ease-in',
                      background: snapshot.isDraggingOver ? '#f0f4f5' : '#fff',
                    }}
                    onClick={() => handleOpen(timeStamp, day)}
                    role="button"
                    onKeyDown={() => handleOpen(timeStamp, day)}
                    tabIndex={0}
                  >
                    {events &&
                      events.map((e: IEvents, i: number) =>
                        renderBlocks(e, i, timeStamp, day)
                      )}
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            ))}
          </div>
        ))}
    </div>
  );
};

export default memo(Table);

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question