From 3226556cd9a49117ac39b05a7c0cd44cba7b892e Mon Sep 17 00:00:00 2001
From: Khaleel Al-Adhami <khaleel.aladhami@gmail.com>
Date: Thu, 20 Feb 2025 13:00:29 -0800
Subject: [PATCH] expose toast

---
 reflex/app.py                     | 10 ++++------
 reflex/components/core/banner.py  | 11 ++++++-----
 reflex/components/sonner/toast.py |  1 -
 3 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/reflex/app.py b/reflex/app.py
index 6f97d3bb3..6e66257b4 100644
--- a/reflex/app.py
+++ b/reflex/app.py
@@ -75,6 +75,7 @@ from reflex.components.core.client_side_routing import (
 from reflex.components.core.sticky import sticky
 from reflex.components.core.upload import Upload, get_upload_dir
 from reflex.components.radix import themes
+from reflex.components.sonner.toast import toast
 from reflex.config import ExecutorType, environment, get_config
 from reflex.event import (
     _EVENT_FIELDS,
@@ -411,7 +412,7 @@ class App(MiddlewareMixin, LifespanMixin):
     ] = default_backend_exception_handler
 
     # Put the toast provider in the app wrap.
-    bundle_toaster: bool = True
+    toaster: Component | None = dataclasses.field(default_factory=toast.provider)
 
     @property
     def api(self) -> FastAPI | None:
@@ -1186,15 +1187,12 @@ class App(MiddlewareMixin, LifespanMixin):
             # Add the custom components from the page to the set.
             custom_components |= component._get_all_custom_components()
 
-        if self.bundle_toaster:
+        if (toaster := self.toaster) is not None:
             from reflex.components.component import memo
-            from reflex.components.sonner.toast import toast
-
-            internal_toast_provider = toast.provider()
 
             @memo
             def memoized_toast_provider():
-                return internal_toast_provider
+                return toaster
 
             toast_provider = Fragment.create(memoized_toast_provider())
 
diff --git a/reflex/components/core/banner.py b/reflex/components/core/banner.py
index e8c72daf6..c0e88b23e 100644
--- a/reflex/components/core/banner.py
+++ b/reflex/components/core/banner.py
@@ -17,7 +17,7 @@ from reflex.components.radix.themes.components.dialog import (
 )
 from reflex.components.radix.themes.layout.flex import Flex
 from reflex.components.radix.themes.typography.text import Text
-from reflex.components.sonner.toast import ToastProps
+from reflex.components.sonner.toast import ToastProps, toast_ref
 from reflex.config import environment
 from reflex.constants import Dirs, Hooks, Imports
 from reflex.constants.compiler import CompileVars
@@ -114,11 +114,11 @@ class ConnectionToaster(Fragment):
         if environment.REFLEX_DOES_BACKEND_COLD_START.get():
             loading_message = Var.create("Backend is starting.")
             backend_is_loading_toast_var = Var(
-                f"toast.loading({loading_message!s}, {{...toast_props, description: '', closeButton: false, onDismiss: () => setUserDismissed(true)}},)"
+                f"toast?.loading({loading_message!s}, {{...toast_props, description: '', closeButton: false, onDismiss: () => setUserDismissed(true)}},)"
             )
             backend_is_not_responding = Var.create("Backend is not responding.")
             backend_is_down_toast_var = Var(
-                f"toast.error({backend_is_not_responding!s}, {{...toast_props, description: '', onDismiss: () => setUserDismissed(true)}},)"
+                f"toast?.error({backend_is_not_responding!s}, {{...toast_props, description: '', onDismiss: () => setUserDismissed(true)}},)"
             )
             toast_var = Var(
                 f"""
@@ -139,10 +139,11 @@ setTimeout(() => {{
                 f"Cannot connect to server: {connection_error}."
             )
             toast_var = Var(
-                f"toast.error({loading_message!s}, {{...toast_props, onDismiss: () => setUserDismissed(true)}},)"
+                f"toast?.error({loading_message!s}, {{...toast_props, onDismiss: () => setUserDismissed(true)}},)"
             )
 
         individual_hooks = [
+            Var(f"const toast = {toast_ref};"),
             f"const toast_props = {LiteralVar.create(props)!s};",
             "const [userDismissed, setUserDismissed] = useState(false);",
             "const [waitedForBackend, setWaitedForBackend] = useState(false);",
@@ -164,7 +165,7 @@ setTimeout(() => {{
             {toast_var!s}
         }}
     }} else {{
-        toast.dismiss("{toast_id}");
+        toast?.dismiss("{toast_id}");
         setUserDismissed(false);  // after reconnection reset dismissed state
     }}
 }}
diff --git a/reflex/components/sonner/toast.py b/reflex/components/sonner/toast.py
index eabc9ea6a..247b897b8 100644
--- a/reflex/components/sonner/toast.py
+++ b/reflex/components/sonner/toast.py
@@ -383,7 +383,6 @@ class Toaster(Component):
         Returns:
             The toaster component.
         """
-        cls.is_used = True
         return super().create(*children, **props)