Просмотр исходного кода

fix toast provider needed (#4801)

* fix toast provider needed

* fix tests
Khaleel Al-Adhami 3 месяцев назад
Родитель
Сommit
6cbdd00169

+ 24 - 1
reflex/app.py

@@ -355,6 +355,9 @@ class App(MiddlewareMixin, LifespanMixin):
         [Exception], Union[EventSpec, List[EventSpec], None]
         [Exception], Union[EventSpec, List[EventSpec], None]
     ] = default_backend_exception_handler
     ] = default_backend_exception_handler
 
 
+    # Put the toast provider in the app wrap.
+    bundle_toaster: bool = True
+
     @property
     @property
     def api(self) -> FastAPI | None:
     def api(self) -> FastAPI | None:
         """Get the backend api.
         """Get the backend api.
@@ -1010,6 +1013,10 @@ class App(MiddlewareMixin, LifespanMixin):
         should_compile = self._should_compile()
         should_compile = self._should_compile()
 
 
         if not should_compile:
         if not should_compile:
+            if self.bundle_toaster:
+                from reflex.components.sonner.toast import Toaster
+
+                Toaster.is_used = True
             with console.timing("Evaluate Pages (Backend)"):
             with console.timing("Evaluate Pages (Backend)"):
                 for route in self._unevaluated_pages:
                 for route in self._unevaluated_pages:
                     console.debug(f"Evaluating page: {route}")
                     console.debug(f"Evaluating page: {route}")
@@ -1039,6 +1046,20 @@ class App(MiddlewareMixin, LifespanMixin):
             + adhoc_steps_without_executor,
             + adhoc_steps_without_executor,
         )
         )
 
 
+        if self.bundle_toaster:
+            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
+
+            toast_provider = Fragment.create(memoized_toast_provider())
+
+            app_wrappers[(1, "ToasterProvider")] = toast_provider
+
         with console.timing("Evaluate Pages (Frontend)"):
         with console.timing("Evaluate Pages (Frontend)"):
             for route in self._unevaluated_pages:
             for route in self._unevaluated_pages:
                 console.debug(f"Evaluating page: {route}")
                 console.debug(f"Evaluating page: {route}")
@@ -1081,7 +1102,9 @@ class App(MiddlewareMixin, LifespanMixin):
             component = app_wrap(self._state is not None)
             component = app_wrap(self._state is not None)
             if component is not None:
             if component is not None:
                 app_wrappers[key] = component
                 app_wrappers[key] = component
-                custom_components |= component._get_all_custom_components()
+
+        for component in app_wrappers.values():
+            custom_components |= component._get_all_custom_components()
 
 
         if self.error_boundary:
         if self.error_boundary:
             console.deprecate(
             console.deprecate(

+ 0 - 3
reflex/components/component.py

@@ -1792,9 +1792,6 @@ class CustomComponent(Component):
             include_children=include_children, ignore_ids=ignore_ids
             include_children=include_children, ignore_ids=ignore_ids
         )
         )
         yield from filter(lambda prop: isinstance(prop, Var), self.props.values())
         yield from filter(lambda prop: isinstance(prop, Var), self.props.values())
-        yield from self.get_component(self)._get_vars(
-            include_children=include_children, ignore_ids=ignore_ids
-        )
 
 
     @lru_cache(maxsize=None)  # noqa: B019
     @lru_cache(maxsize=None)  # noqa: B019
     def get_component(self) -> Component:
     def get_component(self) -> Component:

+ 5 - 1
reflex/components/sonner/toast.py

@@ -8,6 +8,7 @@ from reflex.base import Base
 from reflex.components.component import Component, ComponentNamespace
 from reflex.components.component import Component, ComponentNamespace
 from reflex.components.lucide.icon import Icon
 from reflex.components.lucide.icon import Icon
 from reflex.components.props import NoExtrasAllowedProps, PropsBase
 from reflex.components.props import NoExtrasAllowedProps, PropsBase
+from reflex.constants.base import Dirs
 from reflex.event import EventSpec, run_script
 from reflex.event import EventSpec, run_script
 from reflex.style import Style, resolved_color_mode
 from reflex.style import Style, resolved_color_mode
 from reflex.utils import format
 from reflex.utils import format
@@ -27,7 +28,10 @@ LiteralPosition = Literal[
     "bottom-right",
     "bottom-right",
 ]
 ]
 
 
-toast_ref = Var(_js_expr="refs['__toast']")
+toast_ref = Var(
+    _js_expr="refs['__toast']",
+    _var_data=VarData(imports={f"$/{Dirs.STATE_PATH}": [ImportVar(tag="refs")]}),
+)
 
 
 
 
 class ToastAction(Base):
 class ToastAction(Base):

+ 7 - 1
reflex/components/sonner/toast.pyi

@@ -9,9 +9,12 @@ from reflex.base import Base
 from reflex.components.component import Component, ComponentNamespace
 from reflex.components.component import Component, ComponentNamespace
 from reflex.components.lucide.icon import Icon
 from reflex.components.lucide.icon import Icon
 from reflex.components.props import NoExtrasAllowedProps, PropsBase
 from reflex.components.props import NoExtrasAllowedProps, PropsBase
+from reflex.constants.base import Dirs
 from reflex.event import EventSpec, EventType
 from reflex.event import EventSpec, EventType
 from reflex.style import Style
 from reflex.style import Style
+from reflex.utils.imports import ImportVar
 from reflex.utils.serializers import serializer
 from reflex.utils.serializers import serializer
+from reflex.vars import VarData
 from reflex.vars.base import Var
 from reflex.vars.base import Var
 
 
 LiteralPosition = Literal[
 LiteralPosition = Literal[
@@ -22,7 +25,10 @@ LiteralPosition = Literal[
     "bottom-center",
     "bottom-center",
     "bottom-right",
     "bottom-right",
 ]
 ]
-toast_ref = Var(_js_expr="refs['__toast']")
+toast_ref = Var(
+    _js_expr="refs['__toast']",
+    _var_data=VarData(imports={f"$/{Dirs.STATE_PATH}": [ImportVar(tag="refs")]}),
+)
 
 
 class ToastAction(Base):
 class ToastAction(Base):
     label: str
     label: str

+ 6 - 0
tests/units/test_app.py

@@ -1307,8 +1307,11 @@ def test_app_wrap_compile_theme(
         + "<RadixThemesColorModeProvider>"
         + "<RadixThemesColorModeProvider>"
         "<RadixThemesTheme accentColor={\"plum\"} css={{...theme.styles.global[':root'], ...theme.styles.global.body}}>"
         "<RadixThemesTheme accentColor={\"plum\"} css={{...theme.styles.global[':root'], ...theme.styles.global.body}}>"
         "<Fragment>"
         "<Fragment>"
+        "<MemoizedToastProvider/>"
+        "<Fragment>"
         "{children}"
         "{children}"
         "</Fragment>"
         "</Fragment>"
+        "</Fragment>"
         "</RadixThemesTheme>"
         "</RadixThemesTheme>"
         "</RadixThemesColorModeProvider>"
         "</RadixThemesColorModeProvider>"
         + ("</StrictMode>" if react_strict_mode else "")
         + ("</StrictMode>" if react_strict_mode else "")
@@ -1371,8 +1374,11 @@ def test_app_wrap_priority(
         "<RadixThemesColorModeProvider>"
         "<RadixThemesColorModeProvider>"
         "<Fragment2>"
         "<Fragment2>"
         "<Fragment>"
         "<Fragment>"
+        "<MemoizedToastProvider/>"
+        "<Fragment>"
         "{children}"
         "{children}"
         "</Fragment>"
         "</Fragment>"
+        "</Fragment>"
         "</Fragment2>"
         "</Fragment2>"
         "</RadixThemesColorModeProvider>"
         "</RadixThemesColorModeProvider>"
         "</RadixThemesText>"
         "</RadixThemesText>"