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:
| |
These wrappers toggle visibility with CSS (display: none vs block) but children still mount.
rx.toast() is not a renderable component
This fails:
| |
The reason is that rx.toast() is an event action (an EventSpec), not a renderable component. Passing it as a child triggers a ChildrenTypeError:
| |
Even if you tried to call a toast in on_mount inside a responsive wrapper:
| |
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
| |
How it works
- On mount, the client runs the JS code (
window.matchMedia('(max-width: 1024px)').matches) which results intrueif 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.