@ParaBellum577

Как оптимизировать react-beautiful-dnd?

У меня есть календарь по типу гугловского, в котором создаются, шарятся ивенты, при этом есть драг н дроп. Я использую вот эту либу.
Проблема заключается в том, что у меня 500+ дропабл элементов на странице (это дни, разбитые на клеточки по 15 минут), и когда у меня открыто weekly view, при перетаскивании элементов вниз или верх, когда страница скролится, dnd прилично так тормозит. В daily view такого нет, потому что количество клеточек уменьшается в 7 раз. Подскажите, можно ли как-то оптимизировать работу этой либы?
Droppable component выглядит вот так:

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);
  • Вопрос задан
  • 105 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы