Skip to content

[@mantine.core] Transition clear all timers and RAF on rapid state ch… #7773

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

Merged

Conversation

Han5991
Copy link
Contributor

@Han5991 Han5991 commented May 2, 2025

Fix: Prevent animation glitches on rapid state changes in Transition

What

This PR ensures that all timers (transitionTimeoutRef, delayTimeoutRef) and animation frames (rafRef) are cleared before starting a new transition or delay in the useTransition hook.

Why

Previously, only transitionTimeoutRef was cleared when a new transition started. However, when rapidly toggling the transition state, other timers and RAF callbacks (such as delayTimeoutRef and rafRef) could still be pending, leading to animation glitches, state corruption, or unexpected behavior.

How

  • Introduced a clearAllTimeouts function that clears all relevant timers and animation frames.
  • Called clearAllTimeouts at the start of every transition and delay, as well as in the cleanup effect.
  • This guarantees that only the latest transition is active, and no stale callbacks can affect the component state.

Impact

  • Fixes animation glitches when toggling the transition rapidly (e.g., button mashing).
  • Ensures a smooth and predictable transition experience.

fix: #6381

@Han5991 Han5991 force-pushed the feature/fix-use-transition-clearTime branch from 1b3f66f to 8f8f14b Compare May 2, 2025 14:12
@Jackman3005
Copy link

I think this may be related to an issue I found today... We are rendering a button in a table and when scrolling wildly vertical/horizontally in the table we get a crash with "Maxium update depth exceeded". I traced it into the Mantine button and specifically to the line Transition is rendered. We are using AG Grid which I believe will do performant rendering of the rows, i.e. it will mount/unmount the buttons regularly while scrolling to keep only the visible content mounted. Possibly rapid mount/unmount of ~70 buttons causes Transition to misbehave like this?

@Han5991
Copy link
Contributor Author

Han5991 commented May 5, 2025

I think this may be related to an issue I found today... We are rendering a button in a table and when scrolling wildly vertical/horizontally in the table we get a crash with "Maxium update depth exceeded". I traced it into the Mantine button and specifically to the line Transition is rendered. We are using AG Grid which I believe will do performant rendering of the rows, i.e. it will mount/unmount the buttons regularly while scrolling to keep only the visible content mounted. Possibly rapid mount/unmount of ~70 buttons causes Transition to misbehave like this?

Note: This Patch May Help Prevent Maximum Update Depth Error in Transitions

This patch could help mitigate the "Maximum update depth exceeded" error
that sometimes occurs in highly virtualized environments like AG Grid,
where components are mounted and unmounted rapidly.

What’s the Issue?

  • When components (such as Buttons with Transitions) are mounted and unmounted repeatedly,
    previous timers (like setTimeout) or animation frames (requestAnimationFrame)
    may not always be properly cleared.
  • If these leftover timers/RAFs try to update state after the component has unmounted,
    it can trigger unexpected state updates and render loops, resulting in
    React’s "maximum update depth exceeded" error.
  • This is particularly noticeable in setups like AG Grid,
    where cells mount/unmount frequently due to virtualization.

How This Commit May Help

  • The clearAllTimeouts() function is added to immediately clear all timers and RAFs
    when transition state changes or the component unmounts.
  • This helps reduce the chance that setState or similar calls happen on unmounted components,
    and may prevent unnecessary render loops.

Potential Impact and Limitations

  • By clearing side effects (timers/RAFs) promptly when state changes or on unmount,
    only the most recent transition state is processed.
  • This approach could be particularly effective in environments with frequent mount/unmount cycles,
    such as with AG Grid.
  • However, this does not guarantee to solve all cases;
    it is offered as a potential mitigation that can reduce the likelihood of such errors.

Conclusion

This patch may provide a practical way to reduce infinite render loop risks
and animation-related issues caused by transitions.
If issues persist, please provide additional context or a minimal reproduction example
for further investigation.

@rtivital
Copy link
Member

rtivital commented May 5, 2025

Please remove last commit, this PR must point to v7 branch, it should not merge master changes in

@Han5991 Han5991 changed the base branch from master to v7 May 5, 2025 22:27
@Han5991 Han5991 force-pushed the feature/fix-use-transition-clearTime branch from fc87051 to 8f8f14b Compare May 5, 2025 22:43
…anges to prevent animation glitches

- Add clearAllTimeouts to clear transitionTimeoutRef, delayTimeoutRef, and rafRef
- Ensure all timers and RAF are cleared before starting a new transition or delay
- Prevents animation glitches and state corruption when toggling rapidly
@Han5991 Han5991 force-pushed the feature/fix-use-transition-clearTime branch from 8f8f14b to b07caa5 Compare May 6, 2025 10:05
@rtivital rtivital merged commit 9f3f48c into mantinedev:v7 May 8, 2025
1 check passed
@rtivital
Copy link
Member

rtivital commented May 8, 2025

Thanks!

@Han5991 Han5991 deleted the feature/fix-use-transition-clearTime branch June 22, 2025 10:00
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.

Transition exitDuration property not working correctly
3 participants