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.
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").route, the function name becomes the address: index maps to /, and about to /about.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 itThe basket is empty.
Let's go through which lesson each part of the code comes from.
| Code | Concept | Lesson |
|---|---|---|
basket: list[str] = [] | A State var holding data that changes | Lesson 1 |
on_click=BasketState.add_fruit | Event triggers and handlers | Lesson 1 |
rx.cond(... > 0, list, "empty") | Conditional rendering | Lesson 2 |
rx.foreach(BasketState.basket, rx.list.item) | List rendering. You can pass a component function directly | Lesson 3 |
len(self.basket) and if in the handlers | Real Python at runtime | Lesson 4 |
.length() and % 2 == 0 in the UI | Var operations used at compile time | Lesson 4 |
variant="soft", color_scheme="gray" | Styling with props | Lesson 5 |
app.add_page(fruit_basket, route="/") | Registering a page | Lesson 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.
Now that you have the basics, it's time to build a real app.
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.rx.cond.rx.App and add_page.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.