August 19, 2025

Reflex: Show rx.toast() Only on Small Screens

Reflex makes it easy to conditionally render components by screen size using helpers like:

  • rx.desktop_only()
  • rx.tablet_only()
  • rx.mobile_only()
  • rx.mobile_and_tablet()
  • rx.tablet_and_desktop()

Example:

# Tested with Reflex 0.8.5

import reflex as rx

# Works as expected: renders only on mobile & tablet widths
rx.mobile_and_tablet(
    rx.text("Shows on mobile and tablet, but not on desktop"),
)

These wrappers toggle visibility with CSS (display: none vs block) but children still mount.

 

rx.toast() is not a renderable component

This fails:

import reflex as rx

# ❌ Fails at compile time
rx.mobile_and_tablet(
    rx.toast("Shows on mobile and tablet, but not on desktop")
)

The reason is that rx.toast() is an event action (an EventSpec), not a renderable component. Passing it as a child triggers a ChildrenTypeError:

Component Box received child EventSpec(...) ... 
Accepted types are components, state vars, or 
primitive Python types.

Even if you tried to call a toast in on_mount inside a responsive wrapper:

import reflex as rx

# ❌ Show on all screen sizes
rx.mobile_and_tablet(
    rx.el.div(
        on_mount=rx.toast("Shows on mobile and tablet, but not on desktop")
    )
)

it would still show on all sizes because the child mounts regardless of visibility (the wrapper hides via CSS only).

 

Solution: call_script → State callback

import reflex as rx

class UiEvents(rx.State):
    @rx.event
    def toast_if_small(self, is_small: bool):
        if is_small:
            return rx.toast(
                "Shows on mobile and tablet, but not on desktop",
                duration=5000,
            )

@rx.page(route="/")
def index():
    return rx.el.div(
        on_mount=rx.call_script(
            # Use matchMedia; it aligns better with CSS breakpoints than outerWidth
            f"window.matchMedia('(max-width: 1024px)').matches",
            callback=UiEvents.toast_if_small,
        ),
    )

How it works

  1. On mount, the client runs the JS code (window.matchMedia('(max-width: 1024px)').matches) which results in true if width is 1024px or less, otherwise false.

  2. The boolean result is passed to UiEvents.toast_if_small.

  3. The event function returns rx.toast(...) if the condition is met.

 

You may see two toasts in development

Reflex uses React on the client. In dev mode, React’s Strict Mode—enabled by Next.js during development—intentionally double-invokes mounts and effects, so you may see two toasts. Run reflex run --env prod to confirm the single-mount behavior in production.

0 0 votes
Article Rating

Share the knowledge on

Do you like my content? You can support me at
Buy Me A Coffee
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments