Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize timezone dropdown with virtualization and memoization #9896

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

mdrazak2001
Copy link
Contributor

Fixes #9663

28.01.2025_23.27.23_REC.mp4

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary

This PR implements performance optimizations for the timezone dropdown to prevent page freezing issues by adding virtualization and memoization.

  • Added new VirtualizedSelect component in /packages/twenty-front/src/modules/ui/input/components/VirtualizedSelect.tsx using @tanstack/react-virtual for efficient rendering
  • Implemented memoized timezone options with pre-calculated offsets in /packages/twenty-front/src/modules/settings/accounts/constants/AvailableTimezoneOptions.ts
  • Replaced standard Select with VirtualizedSelect in timezone selection components with 40px item height and 300px max height
  • Added scroll position reset and cleanup on dropdown open/close in VirtualizedSelect
  • Optimized timezone filtering by removing GMT/UTC/UCT duplicates and caching filtered results

5 file(s) reviewed, 6 comment(s)
Edit PR Review Bot Settings | Greptile

Comment on lines 17 to 26
// <Select
// dropdownId="settings-accounts-calendar-time-zone"
// dropdownWidth={416}
// label="Time zone"
// fullWidth
// value={findAvailableTimeZoneOption(value)?.value}
// options={AVAILABLE_TIMEZONE_OPTIONS}
// onChange={onChange}
// withSearchInput
// />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Remove commented out code since it's in version control

// eslint-disable-next-line @typescript-eslint/naming-convention
const difference =
getTimezoneOffset(optionA.value) - getTimezoneOffset(optionB.value);
export const createTimeZoneOptions = memoize(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: memoizing this function won't help with performance since it's only called once at module initialization - the AVAILABLE_TIMEZONE_OPTIONS constant already serves as a cache

const timeZoneOptionsMap = IANA_TIME_ZONES.reduce<Record<string, TimezoneSelectOption>>(
(result, ianaTimeZone) => {
const timeZoneLabel = formatTimeZoneLabel(ianaTimeZone);
const timeZoneName = timeZoneLabel.slice(11);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: slicing at index 11 is fragile - consider using a regex or split() to extract the timezone name more reliably

Comment on lines +703 to +708
const rowVirtualizer = useVirtualizer({
count: filteredOptions.length,
getScrollElement: () => parentRef.current,
estimateSize: () => itemHeight,
overscan: 5,
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: overscan value of 5 may be too low for smooth scrolling with variable height items. Consider increasing to 10-20 for better performance

@@ -13,27 +55,41 @@ export const DateTimeSettingsTimeZoneSelect = ({
value = detectTimeZone(),
onChange,
}: DateTimeSettingsTimeZoneSelectProps) => {
const [searchQuery, setSearchQuery] = useState('');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: searchQuery state is defined but setSearchQuery is never used - this may prevent the search functionality from working

Comment on lines +63 to +64
const allOptions = createTimeZoneOptions();
if (!searchQuery) return allOptions;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: createTimeZoneOptions() is called on every search - should be memoized separately to avoid regenerating the full list repeatedly

@charlesBochet
Copy link
Member

Thanks you @mdrazak2001 :)

The virtualizer approach is interesting but I'm surprised this is needed for a dropdown. I'll take a look tomorrow

@etiennejouan
Copy link
Contributor

@charlesBochet, your PR fixes this issue, isn't it ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Timezone Picker freezes the page when open
3 participants