Skip to content

Commit

Permalink
feat: optimize app by reducing rerenders (#1074)
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinWu098 authored Dec 11, 2024
1 parent 34a4088 commit d011ebc
Show file tree
Hide file tree
Showing 30 changed files with 864 additions and 715 deletions.
69 changes: 69 additions & 0 deletions apps/antalmanac/src/components/Calendar/CalendarCourseEvent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Box } from '@material-ui/core';
import { memo } from 'react';
import { shallow } from 'zustand/shallow';

import { CalendarEvent } from '$components/Calendar/CourseCalendarEvent';
import locationIds from '$lib/location_ids';
import { useSelectedEventStore } from '$stores/SelectedEventStore';

export const CalendarCourseEvent = memo(({ event }: { event: CalendarEvent }) => {
const setSelectedEvent = useSelectedEventStore((state) => state.setSelectedEvent, shallow);

const handleClick = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();

setSelectedEvent(e, event);
};

if (event.isCustomEvent) {
return (
<Box onClick={handleClick}>
<Box
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-between',
fontWeight: 500,
fontSize: '0.8rem',
}}
>
<Box>{event.title}</Box>
</Box>

<Box style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'space-between', fontSize: '0.7rem' }}>
<Box>{Object.keys(locationIds).find((key) => locationIds[key] === parseInt(event.building))}</Box>
</Box>
</Box>
);
}

return (
<Box onClick={handleClick}>
<Box
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-between',
fontWeight: 500,
fontSize: '0.8rem',
}}
>
<Box>{event.title}</Box>
<Box style={{ fontSize: '0.8rem' }}> {event.sectionType}</Box>
</Box>
<Box style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'space-between', fontSize: '0.7rem' }}>
<Box>
{event.showLocationInfo
? event.locations.map((location) => `${location.building} ${location.room}`).join(', ')
: event.locations.length > 1
? `${event.locations.length} Locations`
: `${event.locations[0].building} ${event.locations[0].room}`}
</Box>
<Box>{event.sectionCode}</Box>
</Box>
</Box>
);
});

CalendarCourseEvent.displayName = 'CalendarCourseEvent';
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Box } from '@mui/material';
import { useCallback, useEffect, useRef } from 'react';
import { EventWrapperProps } from 'react-big-calendar';
import { shallow } from 'zustand/shallow';

import type { CalendarEvent } from '$components/Calendar/CourseCalendarEvent';
import { useSelectedEventStore } from '$stores/SelectedEventStore';

interface CalendarCourseEventWrapperProps extends EventWrapperProps<CalendarEvent> {
children?: React.ReactNode;
}

/**
* CalendarCourseEventWrapper allows us to override the default onClick event behavior which problamtically rerenders the entire calendar
*/
export const CalendarCourseEventWrapper = ({ children, ...props }: CalendarCourseEventWrapperProps) => {
const ref = useRef<HTMLDivElement>(null);

const setSelectedEvent = useSelectedEventStore((state) => state.setSelectedEvent, shallow);

const handleClick = useCallback(
(e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();

setSelectedEvent(e, props.event);
},
[props.event, setSelectedEvent]
);

useEffect(() => {
const node = ref.current;
if (!node) {
return;
}

const rbcEvent = node.querySelector('.rbc-event') as HTMLDivElement;
if (!rbcEvent) {
return;
}

rbcEvent.onclick = (e) => handleClick(e as unknown as React.MouseEvent); // the native onclick requires a little type hacking
}, [handleClick]);

return <Box ref={ref}>{children}</Box>;
};
58 changes: 58 additions & 0 deletions apps/antalmanac/src/components/Calendar/CalendarEventPopover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Popover } from '@mui/material';
import { useCallback, useEffect, useState } from 'react';
import { shallow } from 'zustand/shallow';

import CourseCalendarEvent from '$components/Calendar/CourseCalendarEvent';
import AppStore from '$stores/AppStore';
import { useSelectedEventStore } from '$stores/SelectedEventStore';

export function CalendarEventPopover() {
const [anchorEl, selectedEvent, setSelectedEvent] = useSelectedEventStore(
(state) => [state.selectedEventAnchorEl, state.selectedEvent, state.setSelectedEvent],
shallow
);

const [scheduleNames, setScheduleNames] = useState(() => AppStore.getScheduleNames());

const handleClosePopover = useCallback(() => {
setSelectedEvent(null, null);
}, [setSelectedEvent]);

useEffect(() => {
const updateScheduleNames = () => {
setScheduleNames(AppStore.getScheduleNames());
};

AppStore.on('scheduleNamesChange', updateScheduleNames);

return () => {
AppStore.off('scheduleNamesChange', updateScheduleNames);
};
}, []);

if (!selectedEvent) {
return null;
}

return (
<Popover
anchorEl={anchorEl}
open={Boolean(anchorEl) && !!selectedEvent}
onClose={handleClosePopover}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'left',
}}
>
<CourseCalendarEvent
closePopover={handleClosePopover}
selectedEvent={selectedEvent}
scheduleNames={scheduleNames}
/>
</Popover>
);
}
Loading

0 comments on commit d011ebc

Please sign in to comment.