У меня есть календарь по типу гугловского, в котором создаются, шарятся ивенты, при этом есть драг н дроп. Я использую вот эту
либу.
Проблема заключается в том, что у меня 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);