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
Dynamic rendering

Match

Workshop order

Add an order status badge to the delivery order screen. Received, cooking, out for delivery, delivered and cancelled each need their own icon and color.

rx.match compares one value against several cases and shows the component of the case that matches. It's the same idea as Python's match/case. rx.cond only chooses between two branches, so with three or more, rx.match is far easier to read than nested rx.conds. It looks like this.

rx.match(
    condition,
    (case_1, component_1),
    (case_2, component_2),
    ...
    default_component,
)
  • First argument (condition): the value to compare. Usually a State variable.
  • (case, component) tuples: if the value equals the case, that component is shown. Cases are compared from top to bottom.
  • The final non-tuple argument: the default, used when no case matches.

Pick a breed below and the matching sentence appears; pick pug or corgi, which are in the list but have no case, and the default appears.

Unknown cat breed selected.

class MatchBasicState(rx.State):
    cat_breed: str = ""
    animal_options: list[str] = ["persian", "siamese", "maine coon", "ragdoll", "pug", "corgi"]

    @rx.event
    def set_cat_breed(self, breed: str):
        self.cat_breed = breed


rx.flex(
    rx.match(
        MatchBasicState.cat_breed,
        ("persian", rx.text("Persian cat selected.")),
        ("siamese", rx.text("Siamese cat selected.")),
        ("maine coon", rx.text("Maine Coon cat selected.")),
        ("ragdoll", rx.text("Ragdoll cat selected.")),
        rx.text("Unknown cat breed selected."),
    ),
    rx.select.root(
        rx.select.trigger(placeholder="Pick a breed"),
        rx.select.content(
            rx.select.group(
                rx.foreach(MatchBasicState.animal_options, lambda x: rx.select.item(x, value=x)),
            ),
        ),
        value=MatchBasicState.cat_breed,
        on_change=MatchBasicState.set_cat_breed,
    ),
    direction="column",
    spacing="2",
)

Try the values

rx.match has no styling props, so change the value being compared instead. If a tuple lists several cases, as the second one does, matching any one of them is enough. In a real app, a State variable goes where "paid" is.

Try the props

Paid

status

rx.match(
    "paid",
    ("paid", rx.badge(rx.icon("credit-card", size=14), "Paid", color_scheme="blue")),
    ("packing", "shipping", rx.badge(rx.icon("truck", size=14), "On the way", color_scheme="orange")),
    ("done", rx.badge(rx.icon("circle-check", size=14), "Delivered", color_scheme="green")),
    rx.badge(rx.icon("circle-help", size=14), "Unknown", color_scheme="gray"),
)
packing and shipping share the same badge. A value with no case (refunded) falls through to the default at the end.
ArgumentValuesUse
first (cond)Var or valueValue to compare
(case, …, result)tuple (2 or more items)Returns the last item if the value equals any of the items before it
last argumentcomponent or valueDefault. Can be omitted when results are components (an empty rx.fragment())

Rules for the default

  • The default is the non-tuple argument at the very end. Every non-tuple argument is treated as a default, so putting one in the middle is an error.
  • There is only one default. Two is an error.
  • When results are components, the default can be omitted; then rx.fragment() (nothing) becomes the default.
  • When results are values that aren't components (strings and so on), the default is required.
  • A case tuple needs at least two items: a case and a result.

The code below demonstrates these rules in turn; everything except number 3 fails when the component is built.

# 1) default is not last -> error
rx.match(
    MatchState.cat_breed,
    ("persian", rx.text("persian cat selected")),
    rx.text("Unknown cat breed selected."),
    ("siamese", rx.text("siamese cat selected")),
)

# 2) two defaults -> error
rx.match(
    MatchState.cat_breed,
    ("persian", rx.text("persian cat selected")),
    ("siamese", rx.text("siamese cat selected")),
    rx.text("Unknown cat breed selected."),
    rx.text("Another unknown cat breed selected."),
)

# 3) OK: components without a default -> rx.fragment() is the default
rx.match(
    MatchState.cat_breed,
    ("persian", rx.text("persian cat selected")),
    ("siamese", rx.text("siamese cat selected")),
)

# 4) plain values without a default -> error
rx.match(
    MatchState.cat_breed,
    ("persian", "persian cat selected"),
    ("siamese", "siamese cat selected"),
)

# 5) a case tuple needs at least two items -> error
rx.match(
    MatchState.cat_breed,
    ("persian",),
    ("maine coon", rx.text("Maine Coon cat selected")),
)

Several values in one case

List several cases in a tuple and put the result last. The last item in the tuple is always the result. Here three cat breeds, two dog breeds and two horse breeds each share one sentence. football and golf appear nowhere, so the default shows.

Unknown animal breed

class MatchMultiState(rx.State):
    animal_breed: str = ""
    animal_options: list[str] = ["persian", "siamese", "maine coon", "pug", "corgi", "mustang", "rahvan", "football", "golf"]

    @rx.event
    def set_animal_breed(self, breed: str):
        self.animal_breed = breed


rx.flex(
    rx.match(
        MatchMultiState.animal_breed,
        ("persian", "siamese", "maine coon", rx.text("Breeds of cats.")),
        ("pug", "corgi", rx.text("Breeds of dogs.")),
        ("mustang", "rahvan", rx.text("Breeds of horses.")),
        rx.text("Unknown animal breed"),
    ),
    rx.select.root(
        rx.select.trigger(placeholder="Pick one"),
        rx.select.content(
            rx.select.group(
                rx.foreach(MatchMultiState.animal_options, lambda x: rx.select.item(x, value=x)),
            ),
        ),
        value=MatchMultiState.animal_breed,
        on_change=MatchMultiState.set_animal_breed,
    ),
    direction="column",
    spacing="2",
)

Using it as a prop value

Like rx.cond, rx.match can go in a prop when its results are values. The badge's color_scheme below is red when the value is 1, blue for 2, purple for 6, orange for 10 and green otherwise. Cases can be numbers too.

0
class MatchPropState(rx.State):
    value: int = 0

    @rx.event
    def incr(self):
        self.value += 1

    @rx.event
    def decr(self):
        self.value -= 1


rx.flex(
    rx.button("decrement", on_click=MatchPropState.decr, color_scheme="red"),
    rx.badge(
        MatchPropState.value,
        color_scheme=rx.match(
            MatchPropState.value,
            (1, "red"),
            (2, "blue"),
            (6, "purple"),
            (10, "orange"),
            "green",
        ),
        size="2",
    ),
    rx.button("increment", on_click=MatchPropState.incr),
    align_items="center",
    spacing="3",
)

Grouping several values into one case works the same way in props. 1, 3 and 9 are red; 2, 4 and 5 blue; 6, 8 and 12 purple; 10, 15, 20 and 25 orange.

0
class MatchMultiPropState(rx.State):
    value: int = 0

    @rx.event
    def incr(self):
        self.value += 1

    @rx.event
    def decr(self):
        self.value -= 1


rx.flex(
    rx.button("decrement", on_click=MatchMultiPropState.decr, color_scheme="red"),
    rx.badge(
        MatchMultiPropState.value,
        color_scheme=rx.match(
            MatchMultiPropState.value,
            (1, 3, 9, "red"),
            (2, 4, 5, "blue"),
            (6, 8, 12, "purple"),
            (10, 15, 20, 25, "orange"),
            "green",
        ),
        size="2",
    ),
    rx.button("increment", on_click=MatchMultiPropState.incr),
    align_items="center",
    spacing="3",
)

True or false? Use cond

rx.match is for comparing against many values. If the only possibilities are True/False, rx.cond is the right fit, as in rx.cond(State.value == 10, "true value", "false value").

Filling the order

A single status string splits into five branches. The last one, cancelled, isn't written as a case; it is caught by the default. Press the button to move to the next status.

Receivedreceived
MATCH_ORDER_STEPS = ["received", "cooking", "delivering", "delivered", "cancelled"]


class MatchOrderState(rx.State):
    status: str = "received"

    @rx.event
    def next_step(self):
        i = MATCH_ORDER_STEPS.index(self.status)
        self.status = MATCH_ORDER_STEPS[(i + 1) % len(MATCH_ORDER_STEPS)]


rx.hstack(
    rx.match(
        MatchOrderState.status,
        ("received", rx.badge(rx.icon("clipboard-check", size=14), "Received", color_scheme="gray")),
        ("cooking", rx.badge(rx.icon("chef-hat", size=14), "Cooking", color_scheme="amber")),
        ("delivering", rx.badge(rx.icon("bike", size=14), "On the way", color_scheme="blue")),
        ("delivered", rx.badge(rx.icon("house", size=14), "Delivered", color_scheme="green")),
        rx.badge(rx.icon("ban", size=14), "Cancelled", color_scheme="red"),
    ),
    rx.button("Next status", on_click=MatchOrderState.next_step, size="1", variant="soft"),
    rx.code(MatchOrderState.status),
    align="center",
    spacing="3",
)

Workshop notes

  • rx.match(value, (case, result), ..., default). Use it instead of nested cond for three or more branches.

  • Several cases in one tuple: ("a", "b", result). The last item of a tuple is the result.

  • One default, at the very end. Optional when results are components, required when they are values.

  • When results are values, it can go in props such as color_scheme.

  • For two branches, true or false, use rx.cond.

← Previous

Dynamic rendering · Cond

Next →

Dynamic rendering · Foreach

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