To-do lists, comments, product cards: whenever the same shape repeats on a page, you draw it from list data. In this lesson, you'll use rx.foreach to render a list stored in State.
class ListState(rx.State):
items: list[str] = ["Apple", "Banana", "Cherry"]
def render_item(item: rx.Var[str]):
# Render a single item.
# Note that item here is a Var, not a str!
return rx.list.item(item)
def show_fruits():
return rx.list.unordered(
rx.foreach(ListState.items, render_item),
)localhost:3000
Live previewYou pass two things to rx.foreach:
ListState.itemsrender_item. Pass the function itself, without parentheses.Reflex applies render_item to each item in the list to build the components. If items are added to or removed from the list later, the list on the page updates too. You'll see this for yourself with the fruit basket in Lesson 6.
Notice that the item that render_item receives is typed rx.Var[str], not str. This matters.
render_item is a UI function too, so it runs only once, when the app starts. At that point there's no telling what the list will contain, so item is a Var that points to "a value to be filled in later."len(item). Instead, you use the Var operations Reflex provides for Vars: item.length() gives the number of characters, and item.upper() gives the uppercase version. This is also the topic of Lesson 4.For the same reason, a Python list comprehension like [rx.list.item(i) for i in ListState.items] won't work either. To loop over a list in State, always use rx.foreach.
items and check that they appear on the page.render_item to return rx.badge(item) instead of rx.list.item. The same data is drawn in a different shape.items when you click a button. The answer is in Lesson 6.rx.foreach.rx.foreach rather than a list comprehension for lists in State.← Previous
Lesson 2 · Now you see it: conditional rendering
Next →
Lesson 4 · Why doesn't if work? Compile time vs. runtime
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.