The Component Workshop: Reflex's 100 Library Components
·
Course overview
Layout
·
Box
·
Flex
·
Stack
·
Grid
·
Container
·
Section
·
Center
·
Spacer
·
Separator
·
Card
·
Inset
·
Aspect Ratio
·
Fragment
Typography
·
Text
·
Heading
·
Link
·
Code
·
Markdown
·
Blockquote
·
Quote
·
Strong
·
Em
·
Kbd
Forms
·
Button
·
Input
·
Text Area
·
Checkbox
·
Switch
·
Radio Group
·
Select
·
Slider
·
Form
·
Upload
Data display
·
Badge
·
Avatar
·
Icon
·
Callout
·
List
·
Data List
·
Code Block
·
Progress
·
Spinner
·
Scroll Area
·
Moment
Disclosure
·
Tabs
·
Accordion
·
Segmented Control
Overlay
·
Tooltip
·
Popover
·
Hover Card
·
Dialog
·
Alert Dialog
·
Drawer
·
Dropdown Menu
·
Context Menu
·
Toast
Dynamic rendering
·
Cond
·
Match
·
Foreach
·
Auto Scroll
Media
·
Image
·
Audio
·
Video
Tables and data grids
·
Table
·
Data Table
·
Data Editor
Charts
·
Area Chart
·
Bar Chart
·
Line Chart
·
Composed Chart
·
Pie Chart
·
Radar Chart
·
Radial Bar Chart
·
Scatter Chart
·
Funnel Chart
·
Treemap
·
Sankey Chart
·
Error Bar
Chart parts
·
Axis
·
Cartesian Grid
·
Chart Tooltip
·
Legend
·
Label
·
Reference
·
Brush
Other chart libraries
·
Plotly
·
Pyplot
HTML elements
·
HTML
·
HTML Text
·
HTML Layout
·
HTML Forms
·
HTML Media
·
HTML Tables
·
SVG
Other tools
·
Theme
·
Skeleton
·
Clipboard
·
Html Embed
·
Script
·
Memo
rx.scriptOfficial docs
Workshop order
Show the time zone and language reported by the visitor's browser directly on a card, without going through the server.
rx.script puts a <script> tag on the page to run JavaScript. You either write short code directly or load a JavaScript file with src.
It's safe to use with conditional rendering, so the State can decide whether the script is included. It's especially handy for adding analytics or social widget scripts.
Open the browser console (F12) to see the log.
rx.vstack(
rx.script("console.log('inline javascript')"),
rx.text("Open the browser console (F12) to see the log.", size="2"),
)rx.script has no visible props, so instead of a prop lab, drive it with State. The moment rx.cond becomes true, the script is inserted and runs, changing the text of the paragraph below.
Removing the script doesn't undo what already happened (the changed text). Remember that a script's effects stay on the page.
The script has not run yet.
class ScriptToggleState(rx.State):
enabled: bool = False
@rx.event
def toggle(self):
self.enabled = not self.enabled
rx.vstack(
rx.button(
rx.cond(ScriptToggleState.enabled, "Remove script", "Add script"),
on_click=ScriptToggleState.toggle,
variant="soft",
),
rx.cond(
ScriptToggleState.enabled,
rx.script("document.getElementById('script_toggle_out').textContent = 'Script ran at ' + new Date().toLocaleTimeString();"),
),
rx.text("The script has not run yet.", id="script_toggle_out", size="2"),
)| Prop | Values | Default | Use |
|---|---|---|---|
| first child | JavaScript string | none | Code to run right away. Either a child or src is required |
src | URL | none | JavaScript file to load |
async_ | True / False | none | Run independently as soon as it is downloaded |
defer | True / False | none | Run after the document has been parsed |
type | MIME such as "module" | none | Kind of script |
char_set cross_origin integrity referrer_policy | string | none | Encoding, CORS, integrity check and referrer for external files |
custom_attrs | dict | none | Any other attributes you need, such as data-* |
id key class_name on_mount on_unmount | none | Other accepted props. Any other prop triggers a warning |
Avoid complex inline scripts. Once it's more than two or three lines, it's easier to maintain as a .js file in the assets folder loaded with src.
Pass the data-* attributes that analytics and social scripts require through custom_attrs. This course doesn't load external scripts, so this is shown as code only.
# load assets/my-custom.js (files in assets/ are served under /)
rx.script(src="/my-custom.js")
# tracking/social scripts: pass the data-* attributes they need via custom_attrs
rx.script(
src="//gc.zgo.at/count.js",
custom_attrs={"data-goatcounter": "https://reflextoys.goatcounter.com/count"},
)The official docs explain that rx.script uses Next.js's next/script and that the rendered tag gets data-nscript="afterInteractive".
Reflex 0.10 uses React Router instead of Next.js, and rx.script puts the tag into the document's <head> with react-helmet. So the code above renders roughly like this.
<!-- Reflex 0.10: react-helmet puts it in the document <head> -->
<script src="//gc.zgo.at/count.js" data-goatcounter="https://reflextoys.goatcounter.com/count"></script>For code that should run "once, when the button is clicked" rather than a script that stays on the page, the rx.call_script event is a better fit.
Give it a callback and the JavaScript result comes back to a State handler.
class ScriptCallState(rx.State):
language: str = "unknown"
@rx.event
def receive_language(self, value: str):
self.language = value
rx.hstack(
rx.button(
"Read browser language",
on_click=rx.call_script("navigator.language", callback=ScriptCallState.receive_language),
variant="outline",
),
rx.badge(ScriptCallState.language),
align="center",
)The inline script inserted when the card renders reads the browser's Intl and navigator.language and changes the text of the headings. Nothing is sent to the server.
Your time zone
rx.card(
rx.script(
"const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;"
" document.getElementById('script_order_tz').textContent = tz + ' · ' + navigator.language;"
),
rx.text("Your time zone", size="1", color_scheme="gray"),
# the script rewrites this text before React takes over the page,
# so tell React the mismatch is expected
rx.heading("Detecting...", id="script_order_tz", size="4", custom_attrs={"suppressHydrationWarning": True}),
max_width="320px",
)Workshop notes
rx.script("code") is inline; rx.script(src="/file.js") loads a file. One of the two is required.
Used with rx.cond, the State can add and remove it. Effects that already ran remain.
Past two or three lines, use a .js file in the assets folder. data-* attributes go in custom_attrs.
In 0.10, rx.script goes into <head> through react-helmet, not next/script.
For code that runs once when a button is clicked, rx.call_script(callback=...) fits better.
Get news about new lessons
We'll email you when this course gets new lessons or a follow-up course opens.
R
ReflexKR
Learn Python and Reflex by doing. Every example was run and verified on Reflex 0.10.0.
ReflexKR is free, with no banner ads. If it helped you, you can support it with a coffee. ☕ Buy us a coffee
Affiliate disclosure© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Questions & answers
Ask anything about this lesson. Questions from every language version of this page appear together.