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
-
On mount, the client runs the JS code (
window.matchMedia('(max-width: 1024px)').matches
) which results intrue
if width is 1024px or less, otherwisefalse
. -
The boolean result is passed to
UiEvents.toast_if_small
. -
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.