R

ReflexKR

Reflex Docs

Reflex Basics, Hands-On

·

Course overview

1

Click and it changes: State and events

2

Now you see it: conditional rendering

3

Drawing lists: rx.foreach

4

Why doesn't if work? Compile time vs. runtime

5

Making it look good: components, props and style

6

Apps, pages and a fruit basket

Reflex Basics, Hands-On
Lesson 6

Time 0:34–0:40

Apps, pages and a fruit basket

This is the last lesson. You'll see how to hook the UI functions you've built up to real web addresses, then bring together everything from Lessons 1 to 5 into one small app.

6-1. Apps and pages (2 min)

You create a Reflex app with rx.App and connect UI functions to web addresses (routes) with add_page.

def index():
    return rx.text("Root Page")


app = rx.App()
app.add_page(index, route="/")
  • app = rx.App() must be at the top level of your main file. Reflex looks for your app under the name app.
  • route="/" is your site's home page. You can keep adding pages, as in app.add_page(about, route="/about").
  • If you leave out route, the function name becomes the address: index maps to /, and about to /about.

6-2. Putting it all together: a fruit basket (4 min)

This basket lets you add and remove fruit with buttons. It's short, but it uses every concept in this course.

FRUITS = ["Apple", "Banana", "Cherry", "Grape", "Mango", "Peach"]


class BasketState(rx.State):
    basket: list[str] = []

    @rx.event
    def add_fruit(self):
        # Event handlers run real Python: pick the next fruit in the list.
        self.basket.append(FRUITS[len(self.basket) % len(FRUITS)])

    @rx.event
    def remove_last(self):
        if self.basket:
            self.basket.pop()


def fruit_basket():
    return rx.vstack(
        rx.hstack(
            rx.heading("My basket", as_="h2", size="5"),
            # Var operations: .length() and % work on vars in components.
            rx.badge(BasketState.basket.length()),
            rx.cond(
                BasketState.basket.length() % 2 == 0,
                rx.badge("even", color_scheme="green"),
                rx.badge("odd", color_scheme="orange"),
            ),
            align="center",
        ),
        rx.cond(
            BasketState.basket.length() > 0,
            rx.list.unordered(rx.foreach(BasketState.basket, rx.list.item)),
            rx.text("The basket is empty.", color_scheme="gray"),
        ),
        rx.hstack(
            rx.button("Add fruit", on_click=BasketState.add_fruit),
            rx.button("Remove last", on_click=BasketState.remove_last, variant="soft"),
        ),
        align="start",
    )


app = rx.App()
app.add_page(fruit_basket, route="/")

localhost:3000

Try it

My basket

0even

The basket is empty.

Click Add fruit and Remove last. The count, the even/odd badge and the list all update together.

Let's go through which lesson each part of the code comes from.

CodeConceptLesson
basket: list[str] = []A State var holding data that changesLesson 1
on_click=BasketState.add_fruitEvent triggers and handlersLesson 1
rx.cond(... > 0, list, "empty")Conditional renderingLesson 2
rx.foreach(BasketState.basket, rx.list.item)List rendering. You can pass a component function directlyLesson 3
len(self.basket) and if in the handlersReal Python at runtimeLesson 4
.length() and % 2 == 0 in the UIVar operations used at compile timeLesson 4
variant="soft", color_scheme="gray"Styling with propsLesson 5
app.add_page(fruit_basket, route="/")Registering a pageLesson 6

Notice how the same len works in a handler but becomes .length() in the UI. If you can answer Lesson 4's question, "When does this code run?", you've got the Reflex basics down.

Next steps

Now that you have the basics, it's time to build a real app.

Exercises

  1. Change add_fruit so the same fruit never goes into the basket twice. You're inside a handler, so you can use if fruit not in self.basket.
  2. Add a "Clear" button that empties the basket in one go.
  3. Show a "Full!" badge once the basket holds 5 or more fruits. This is UI code, so use Var operations and rx.cond.

Checkpoint

  • You can register a page with rx.App and add_page.
  • You can explain which concept each line of the fruit basket code uses.
  • You know why the same calculation uses different syntax in a handler than in the UI.

← Previous

Lesson 5 · Making it look good: components, props and style

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