Skip to content

fix(date-picker): eliminate infinite re-render crash on re-open with existing selection#4609

Merged
waleedlatif1 merged 3 commits into
stagingfrom
fix/date-picker-and-quota-cleanup
May 15, 2026
Merged

fix(date-picker): eliminate infinite re-render crash on re-open with existing selection#4609
waleedlatif1 merged 3 commits into
stagingfrom
fix/date-picker-and-quota-cleanup

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Date-picker crash (root cause fix): The useEffect that syncs picker state on open had initialStart and initialEndDate objects computed fresh on every render — in its dependency array. Because Object.is returns false for any two distinct Date instances, the effect re-fired on every render while open=true, calling setRangeStart/setRangeEnd, triggering another render, and repeating until React's re-render limit was hit and the page crashed with "Something went wrong." Reproduced by: select a custom date range with time enabled, then click the picker again. Fix: compute start/end as local variables inside the effect; use the stable string props (props.startDate, props.endDate) as deps instead.

  • Multipart quota guard cleanup: Removes the redundant typeof fileSize === 'number' condition from the quota check. fileSize is typed as number (required) in initiateMultipartBodySchema so the typeof guard was dead code. Uses fileSize ?? 0 as a defensive fallback (the ?? 0 is unreachable but clarifies intent for future readers).

  • JSDoc clarification: Improves the QUOTA_EXEMPT_STORAGE_CONTEXTS comment to explain that logs is unreachable via the multipart endpoint (rejected at context validation) but active for non-multipart paths used by the execution logging pipeline.

Test plan

  • Select a custom date range with time enabled in the Logs view
  • Click the time picker button again — confirm the date picker opens without crashing
  • Apply a new range and confirm it saves correctly
  • Confirm quota enforcement still blocks over-limit uploads (existing tests pass)

…ng selection

The useEffect that syncs picker state on open had initialStart and
initialEnd — Date objects computed on every render — in its dependency
array. Because Object.is returns false for any two distinct Date
instances, the effect fired on every render when open=true, calling
setRangeStart/setRangeEnd and triggering another render, producing an
infinite loop that crashed the page.

Fix: compute start and end as local variables inside the effect and
use the stable string props (props.startDate, props.endDate) as deps
instead.

Also removes the redundant typeof fileSize === 'number' guard in the
multipart quota check — fileSize is z.number() (required) in the
contract so it can never be undefined at that point.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 15, 2026 1:29am

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 15, 2026

PR Summary

Medium Risk
Updates date-picker state syncing and multipart quota enforcement; while changes are localized, they affect a shared UI component and upload limit checks that can block user actions if misapplied.

Overview
Fixes a crash in the DatePicker when reopening a previously-selected range (especially with showTime) by refactoring prop destructuring and reworking the “sync on open” effect to depend on stable raw props, avoiding an infinite re-render loop.

Adjusts multipart upload initiation to always run quota validation for non-exempt contexts and defensively passes fileSize ?? 0, and clarifies QUOTA_EXEMPT_STORAGE_CONTEXTS documentation (including why logs is exempt outside multipart).

Reviewed by Cursor Bugbot for commit 701d325. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 15, 2026

Greptile Summary

This PR fixes a crash in the date-picker caused by an infinite re-render loop, cleans up a dead-code type guard in the multipart upload route, and improves a JSDoc comment in types.ts.

  • Date-picker crash fix: initialStart/initialEnd — fresh Date objects computed on every render — were in the useEffect dependency array, so Object.is returned false each render, causing the effect to fire repeatedly while the picker was open, saturating React's re-render limit. The fix moves Date construction inside the effect and uses the stable string/prop references (startDate, endDate) as deps.
  • Multipart quota guard: Removes the redundant typeof fileSize === 'number' check and uses a defensive fileSize ?? 0 fallback.
  • JSDoc: QUOTA_EXEMPT_STORAGE_CONTEXTS comment clarifies why logs is exempted and notes it is unreachable via the multipart endpoint.

Confidence Score: 5/5

Safe to merge — the fix is targeted and correct, the quota-guard cleanup is additive-safe, and no logic paths are broken.

The root-cause fix (stabilising useEffect deps) directly addresses the crash. The multipart-route change only removes an unreachable type guard; quota enforcement itself is unchanged. No regressions were identified in the changed paths.

No files require special attention, though callers supplying Date object instances rather than strings for startDate/endDate should ensure those references are stable.

Important Files Changed

Filename Overview
apps/sim/components/emcn/components/date-picker/date-picker.tsx Core infinite-re-render crash fixed by moving Date construction inside the effect and using stable string props as deps; additional clean-up of intermediate variables and discriminated-union cast via FlatDatePickerProps.
apps/sim/app/api/files/multipart/route.ts Removes the now-redundant typeof fileSize === 'number' guard; defensive ?? 0 fallback is unreachable but harmless.
apps/sim/lib/uploads/shared/types.ts JSDoc update on QUOTA_EXEMPT_STORAGE_CONTEXTS clarifying why logs is exempted and noting it is unreachable via the multipart endpoint; no logic changes.

Sequence Diagram

sequenceDiagram
    participant User
    participant Trigger as DatePicker Trigger
    participant State as Component State
    participant Effect as useEffect (sync on open)

    User->>Trigger: Click (open false to true)
    Trigger->>State: setInternalOpen(true)
    Note over Effect: open=true, isRangeMode=true
    Effect->>State: parseDate(startDate) sets rangeStart
    Effect->>State: parseDate(endDate) sets rangeEnd
    Effect->>State: setViewMonth / setViewYear
    Note over Effect: Deps are all primitives - no re-fire on re-render

    User->>Trigger: Click (open true to false)
    Trigger->>State: setInternalOpen(false)
    Note over Effect: open=false - early return, no state update
Loading

Reviews (2): Last reviewed commit: "refactor(date-picker): comprehensive cle..." | Re-trigger Greptile

The previous fix still had derived Date objects in useEffect deps.
Object.is(new Date(), new Date()) === false, so any Date in deps causes
the effect to run every render, reproducing the infinite loop on
re-open with existing time selection.

Key changes:
- useEffect deps now use only stable primitives (startDate, endDate strings)
  and compute Date values inside the effect — eliminating the loop
- Replace `rest as any` with a FlatDatePickerProps merged type for safe,
  typed destructuring across the discriminated union
- Remove initialStart/initialEnd render-scope variables; compute inline or
  inside effects to keep derivation local to each use site
- Callbacks use destructured props (onChange, onRangeChange, etc.) instead
  of props.x references
- Remove verbose TSDoc on internal callbacks — names are self-documenting
- Preserve all existing JSX structure and CalendarMonth logic unchanged
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 701d325. Configure here.

@waleedlatif1 waleedlatif1 merged commit 922de38 into staging May 15, 2026
14 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/date-picker-and-quota-cleanup branch May 15, 2026 01:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant