Skip to content

fix(useDatePicker): resolve per-keystroke lag causing CI timeouts (LIBS-763)#101

Merged
kabaros merged 3 commits into
alphafrom
fix/LIBS-763-calendar-timeout
Jul 5, 2026
Merged

fix(useDatePicker): resolve per-keystroke lag causing CI timeouts (LIBS-763)#101
kabaros merged 3 commits into
alphafrom
fix/LIBS-763-calendar-timeout

Conversation

@kabaros

@kabaros kabaros commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Fixes https://dhis2.atlassian.net/browse/DHIS2-21183 and https://dhis2.atlassian.net/browse/LIBS-763

Summary

Typing in CalendarInput was causing severe lag due to values in useDatePicker being rebuilt from scratch on every render instead of only when their actual inputs changed. This was causing the CI timeouts tracked in LIBS-763.

  • useNavigation args weren't stable — the date and options objects passed in were fresh instances every render (withCalendar() returns a new object each call; the options object was an inline literal), which broke useNavigation's internal useMemo and caused the year (up to 126 entries) and month dropdown lists to be rebuilt through Intl on every render.
  • calendarWeekDays and selectedDateZdt weren't memoizedcalendarWeekDays was rebuilt inline on every render, re-running localiseWeekLabel (Intl-backed) for all ~35-42 visible day cells regardless of whether anything changed. selectedDateZdt was similarly unstable, which would have blocked memoizing calendarWeekDays against it even after fixing the above.

Memoized navigationDateZdt, navigationOptions, selectedDateZdt, and calendarWeekDays against their real dependencies. Since selectDate itself is recreated whenever the caller's onDateSelect isn't memoized (the common case), the day-cell onClick handlers read the latest selectDate via a ref instead of closing over it directly, avoiding it as an unstable memo dependency.

Impact

10-keystroke typing benchmark:

Calendar Before After
gregory ~2000ms ~28ms
ethiopic crashed (CLDR48 bug) ~12ms
nepali ~760ms ~14ms

Test plan

  • Existing unit tests pass
  • Manual check: type quickly in CalendarInput for gregory and a non-gregory (e.g. nepali) calendar and confirm no perceptible lag

🤖 Generated with Claude Code

kabaros and others added 2 commits July 3, 2026 16:27
… lag

useNavigation's internal useMemo was invalidated on every render because
its date and options arguments were freshly created inline on every call
(withCalendar() returns a new instance each time, and the options object
was a new literal each time). Since useMemo compares dependencies by
reference, this meant the year (up to 126 entries) and month dropdown
lists were rebuilt through Intl on every single render of CalendarInput,
including every keystroke while typing.

Memoizing both arguments against their real dependencies cuts a 10-keystroke
typing benchmark from ~2000ms to ~300ms for gregory and ~760ms to ~90ms for
nepali, and should resolve the CI timeouts tracked in LIBS-763.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
calendarWeekDays was rebuilt inline in the returned object on every
render, re-running localiseWeekLabel (Intl-backed for non-custom
calendars) for every visible day cell (~35-42 cells) regardless of
whether anything visible had actually changed. selectedDateZdt was
similarly recreated (non-Intl, but unstable, which would have defeated
memoizing calendarWeekDays against it).

Memoized both against their real dependencies. The day-selection
onClick handlers read the latest selectDate through a ref instead of
closing over it directly, since selectDate itself is recreated whenever
the caller's onDateSelect callback isn't memoized (the common case) and
can't be a stable memo dependency.

Combined with the previous useNavigation fix, a 10-keystroke typing
benchmark now runs in ~28ms for gregory (was ~2000ms) and ~14ms for
nepali (was ~760ms).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@codecov-commenter

codecov-commenter commented Jul 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.75%. Comparing base (23e7553) to head (4583db7).
⚠️ Report is 1 commits behind head on alpha.

Additional details and impacted files
@@            Coverage Diff             @@
##            alpha     #101      +/-   ##
==========================================
+ Coverage   94.71%   94.75%   +0.03%     
==========================================
  Files          57       57              
  Lines        1249     1258       +9     
  Branches      352      351       -1     
==========================================
+ Hits         1183     1192       +9     
  Misses         65       65              
  Partials        1        1              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kabaros
kabaros force-pushed the fix/LIBS-763-calendar-timeout branch from a5918f4 to f10b088 Compare July 3, 2026 15:33
@kabaros
kabaros changed the base branch from main to alpha July 3, 2026 15:34
@kabaros
kabaros requested a review from a team July 3, 2026 15:42
Assert on Intl-backed localisation call counts and referential stability
of the memoized navigation/day-cell values, rather than wall-clock timing
(too flaky across CI environments). Also verifies the day-cell onClick
handler always calls the latest onDateSelect via the ref workaround, even
when the calendarWeekDays memo doesn't recompute.

Verified these fail against the pre-fix implementation and pass against
the fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Jul 3, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 New issue
1 New Critical Issues (required ≤ 0)
1 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@kabaros
kabaros merged commit 27dfec4 into alpha Jul 5, 2026
8 of 9 checks passed
@dhis2-bot

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 2.2.0-alpha.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

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.

4 participants