R

ReflexKR

Reflex Docs

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

The Component Workshop: Reflex's 100 Library Components
Other tools

Script

rx.script

Official 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"),
)

Adding and removing a script with State

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"),
)
PropValuesDefaultUse
first childJavaScript stringnoneCode to run right away. Either a child or src is required
srcURLnoneJavaScript file to load
async_True / FalsenoneRun independently as soon as it is downloaded
deferTrue / FalsenoneRun after the document has been parsed
typeMIME such as "module"noneKind of script
char_set cross_origin integrity referrer_policystringnoneEncoding, CORS, integrity check and referrer for external files
custom_attrsdictnoneAny other attributes you need, such as data-*
id key class_name on_mount on_unmountnoneOther accepted props. Any other prop triggers a warning

Keep it short; use a file when it's long

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>

Running on an event: rx.call_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.

unknown
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",
)

Filling the order

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

Detecting...

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.

← Previous

Other tools · Html Embed

Next →

Other tools · Memo

Get news about new lessons

We'll email you when this course gets new lessons or a follow-up course opens.

We collect: your email address · Purpose: news about new lessons or the launch of this course · Kept until: you ask us to remove it. We never use it for anything else or share it. Reply to any notice email and we'll delete it right away.

Questions & answers

Ask anything about this lesson. Questions from every language version of this page appear together.

Shown as plain text, without links or formatting.

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
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex