Reflex Logo

Intro

Gallery

Hosting

Learn

Components

Recipes

API Reference

Onboarding

Library

/

Dynamic-rendering

/

Match

The rx.match feature in Reflex serves as a powerful alternative to rx.cond for handling conditional statements. While rx.cond excels at conditionally rendering two components based on a single condition, rx.match extends this functionality by allowing developers to handle multiple conditions and their associated components. This feature is especially valuable when dealing with intricate conditional logic or nested scenarios, where the limitations of rx.cond might lead to less readable and more complex code.

With rx.match, developers can not only handle multiple conditions but also perform structural pattern matching, making it a versatile tool for managing various scenarios in Reflex applications.

The rx.match function provides a clear and expressive syntax for handling multiple conditions and their corresponding components:

rx.match(
    condition,
    (case_1, component_1),
    (case_2, component_2),
    ...
    default_component,
)
  • condition: The value to match against.
  • (case_i, component_i): A Tuple of matching cases and their corresponding return components.
  • default_component: A special case for the default component when the condition isnt matched by any of the match cases.

Example

Unknown cat breed selected.

from typing import List

import reflex as rx


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


def match_demo():
    return rx.flex(
        rx.match(
            MatchState.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(),
            rx.select.content(
                rx.select.group(
                    rx.foreach(
                        MatchState.animal_options,
                        lambda x: rx.select.item(
                            x, value=x
                        ),
                    )
                ),
            ),
            value=MatchState.cat_breed,
            on_change=MatchState.set_cat_breed,
        ),
        direction="column",
        gap="2",
    )

The default case in rx.match serves as a universal handler for scenarios where none of the specified match cases aligns with the given match condition. Here are key considerations when working with the default case:

  • Placement in the Match Function: The default case must be the last non-tuple argument in the rx.match component. All match cases should be enclosed in tuples; any non-tuple value is automatically treated as the default case. For example:
rx.match(
           MatchState.cat_breed,
           ("persian", rx.text("persian cat selected")),
           rx.text("Unknown cat breed selected."),
           ("siamese", rx.text("siamese cat selected")),
       )

The above code snippet will result in an error due to the misplaced default case.

  • Single Default Case: Only one default case is allowed in the rx.match component. Attempting to specify multiple default cases will lead to an error. For instance:
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.")
       )
  • Optional Default Case for Component Return Values: If the match cases in a rx.match component return components, the default case can be optional. In this scenario, if a default case is not provided, rx.fragment will be implicitly assigned as the default. For example:
rx.match(
           MatchState.cat_breed,
           ("persian", rx.text("persian cat selected")),
           ("siamese", rx.text("siamese cat selected")),
       )

In this case, rx.fragment is the default case. However, not providing a default case for non-component return values will result in an error:

rx.match(
           MatchState.cat_breed,
           ("persian", "persian cat selected"),
           ("siamese", "siamese cat selected"),
       )

The above code snippet will result in an error as a default case must be explicitly provided in this scenario.

rx.match excels in efficiently managing multiple conditions and their corresponding components, providing a cleaner and more readable alternative compared to nested rx.cond structures.

Consider the following example:

Unknown animal breed

from typing import List

import reflex as rx


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


def multi_match_demo():
    return rx.flex(
        rx.match(
            MultiMatchState.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(),
            rx.select.content(
                rx.select.group(
                    rx.foreach(
                        MultiMatchState.animal_options,
                        lambda x: rx.select.item(
                            x, value=x
                        ),
                    )
                ),
            ),
            value=MultiMatchState.animal_breed,
            on_change=MultiMatchState.set_animal_breed,
        ),
        direction="column",
        gap="2",
    )

In a match case tuple, you can specify multiple conditions. The last value of the match case tuple is automatically considered as the return value. It's important to note that a match case tuple should contain a minimum of two elements: a match case and a return value. The following code snippet will result in an error:

rx.match(
    MatchState.cat_breed,
    ("persian",),
    ("maine coon", rx.text("Maine Coon cat selected")),
)

Similar to rx.cond, rx.match can be used as prop values, allowing dynamic behavior for UI components:

0
import reflex as rx


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

    def incr(self):
        self.value += 1

    def decr(self):
        self.value -= 1


def match_prop_demo_():
    return rx.flex(
        rx.button(
            "decrement",
            on_click=MatchPropState.decr,
            background_color="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",
        direction="row",
        gap="3",
    )

In the example above, the background color property of the box component containing State.value changes to red when state.value is 1, blue when its 5, green when its 5, orange when its 15 and black for any other value.

The example below also shows handling multiple conditions with the match component as props.

0
import reflex as rx


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

    def incr(self):
        self.value += 1

    def decr(self):
        self.value -= 1


def match_multi_prop_demo_():
    return rx.flex(
        rx.button(
            "decrement",
            on_click=MatchMultiPropState.decr,
            background_color="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",
        direction="row",
        gap="3",
    )
rx.cond(
    MatchPropState.value == 10, "true value", "false value"
)

Match cases based on a condition.

PropTypeDescriptionValues
condAny

The condition to determine which case to match.

match_casesList

The list of match cases to be matched.

defaultAny

The catchall case to match.

Event Triggers

See the full list of default event triggers
← ForeachButton →

Did you find this useful?

HomeGalleryChangelogIntroductionHosting