Skip to content

animate glitches when month is controlled and the parent rerenders during navigation #2935

@gpbl

Description

@gpbl

Summary

When DayPicker is used with animate and a controlled month prop, the month transition can glitch if the parent rerenders during onMonthChange.

This is easy to reproduce in the Docusaurus playground when month is synced to external state / query-string state, but it looks like a library-level robustness issue rather than a docs-only issue.

Reproduction

function ControlledAnimatedCalendar() {
  const [month, setMonth] = useState(new Date(2026, 3, 1));
  const [tick, setTick] = useState(0);

  return (
    <DayPicker
      animate
      month={month}
      onMonthChange={(nextMonth) => {
        setMonth(nextMonth);
        setTick((x) => x + 1); // simulate external rerender / router update
      }}
    />
  );
}

Actual behavior

The transition can briefly flicker, jump, overlap, or appear to reset mid-flight.

docusaurus-v9.mov

Expected behavior

Animated month transitions should remain stable when month is controlled, even if the parent rerenders during onMonthChange.

vite-app-v10.mov

Notes

  • The Docusaurus playground makes this easy to trigger because it syncs props to the URL.
  • A plain Vite example where month navigation stays internal to DayPicker does not show the same glitch.
  • This suggests the issue is related to controlled animated navigation under extra rerender pressure.

Suspected cause

src/useAnimation.ts appears to update animation snapshots/refs on every render. In controlled mode, parent rerenders during an ongoing transition may cause the animation bookkeeping to be refreshed from an already animating tree, which can desync the transition state from the DOM.

Possible fixes

  1. Only set up animation state when the displayed month actually changes, not on every rerender.
  2. Keep one stable snapshot per transition and avoid overwriting it while an animation is active.
  3. Add a regression test for animate + controlled month + parent rerender in onMonthChange.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugBug or Bug fixes

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions