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

Author: gpblCreated Apr 19, 2026Updated Apr 20, 2026
Labelsbug

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

typescript
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.

https://github.com/user-attachments/assets/9514497c-c1c0-4dc8-b33b-3979131dc2ee

Expected behavior

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

https://github.com/user-attachments/assets/6fce5b66-c73e-41dd-af69-ba641e35d79a

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.