Skip to content

Toast jank/freezes in Edge with default ToastQueue update wrapping (startViewTransition + flushSync)ย #6295

@focus0802

Description

@focus0802

Summary

After migrating from sonner to HeroUI Toast (@heroui/react@3.0.0-beta.8), we observed severe intermittent UI jank/freezes in production.

We tracked it down to the default Toast update path. The issue disappears when Toast is disabled or when ToastQueue is created with a custom wrapUpdate that bypasses startViewTransition.

Environment

  • @heroui/react: 3.0.0-beta.8
  • @heroui/styles: 3.0.0-beta.8
  • React: 19.2.4
  • Browser: Microsoft Edge 145.0.0.0
  • OS: Windows 10 x64

Reproduction Pattern

In app code:

import { ToastQueue } from "@heroui/react";

const messageQueue = new ToastQueue({ maxVisibleToasts: 3 });
const notificationQueue = new ToastQueue({ maxVisibleToasts: 5 });
<Toast.Provider queue={messageQueue} placement="top" />
<Toast.Provider queue={notificationQueue} placement="top end" />

Then:

  1. Trigger normal toast usage (mutation success/error, promise toasts, some persistent notifications with timeout: 0).
  2. Repeatedly refresh page (F5) and do normal operations.

Actual Behavior

  • Intermittent but frequent severe jank (main thread stalls) appears.
  • Once the app enters this jank state, many later operations become consistently laggy.
  • In our tests, after this happens, nearly any later mutation/action stutters.

What We Found

  • Disabling HeroUI Toast entirely removes the issue.
  • Keeping Toast enabled but using this workaround also removes the issue:
const queue = new ToastQueue({
  maxVisibleToasts: 3,
  wrapUpdate: (fn) => fn(),
});
  • Setting maxVisibleToasts to 1 made the issue easier to reproduce in our case.

From local inspection, default queue update uses document.startViewTransition(() => flushSync(fn)) in toast queue internals, which looks strongly related to the jank in Edge.

Expected Behavior

Toast updates should not cause severe UI jank/freezes under normal refresh + action patterns.

Request / Suggestion

Would you consider one of these?

  1. Make startViewTransition behavior opt-in (or disabled by default in production / certain browsers).
  2. Provide a first-class prop/flag on Toast.Provider to disable transition wrapping.
  3. Avoid aggressive flushSync + view-transition combination for every toast update.

Happy to provide more profiling traces if needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions