Skip to content
Merged
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 57 additions & 33 deletions docs/library/dynamic-rendering/foreach.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,64 @@ import reflex as rx

# Foreach

The `rx.foreach` component takes an iterable(list, tuple or dict) and a function that renders each item in the list.
The `rx.foreach` component takes an iterable (list, tuple, or dict) and a function that renders each item in the list.
This is useful for dynamically rendering a list of items defined in a state.

```md alert warning
# `rx.foreach` is specialized for usecases where the iterable is defined in a state var.

For an iterable where the content doesn't change at runtime, i.e a constant, using a list/dict comprehension instead of `rx.foreach` is preferred.
# Use `rx.foreach` for state vars; use Python list or dict comprehensions for constants.
```

```python demo exec
from typing import List


class ForeachState(rx.State):
color: List[str] = ["red", "green", "blue", "yellow", "orange", "purple"]
colors: List[str] = [
"#E5484D",
"#12A594",
"#3E63DD",
"#AD5700",
"#F76B15",
"#8E4EC6",
]


def color_swatch(label, color: rx.Var[str]):
Comment thread
masenf marked this conversation as resolved.
Outdated
return rx.box(
rx.text(label, color="white", weight="medium"),
bg=color,
padding_y="0.5em",
padding_x="0.75em",
min_width="5.5em",
text_align="center",
border_radius="0.375rem",
border="1px solid rgba(0, 0, 0, 0.12)",
box_shadow="0 1px 2px rgba(0, 0, 0, 0.10)",
)


def colored_box(color: str):
return rx.box(rx.text(color), bg=color)
def colored_box(color: rx.Var[str]):
return color_swatch(color, color)


def foreach_example():
return rx.grid(
rx.foreach(ForeachState.color, colored_box),
rx.foreach(ForeachState.colors, colored_box),
columns="2",
)
```

The function can also take an index as a second argument.

```python demo exec
def colored_box_index(color: str, index: int):
return rx.box(rx.text(index), bg=color)
def colored_box_index(color: rx.Var[str], index: int):
Comment thread
masenf marked this conversation as resolved.
Outdated
return color_swatch(index, color)


def foreach_example_index():
return rx.grid(
rx.foreach(
ForeachState.color, lambda color, index: colored_box_index(color, index)
ForeachState.colors, lambda color, index: colored_box_index(color, index)
),
columns="2",
)
Expand All @@ -66,7 +85,7 @@ class NestedForeachState(rx.State):
numbers: List[List[str]] = [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"]]
Comment thread
masenf marked this conversation as resolved.
Outdated


def display_row(row):
def display_row(row: rx.Var[list[str]]):
return rx.hstack(
rx.foreach(
row,
Expand Down Expand Up @@ -101,18 +120,19 @@ class ListState(rx.State):
def add_item(self):
self.items += [self.new_item]

@rx.event
def finish_item(self, item: str):
self.items = [i for i in self.items if i != item]


def get_item(item):
def get_item(item: rx.Var[str]):
return rx.list.item(
rx.hstack(
rx.button(
"Done",
on_click=lambda: ListState.finish_item(item),
height="1.5em",
background_color="white",
border="1px solid blue",
size="1",
variant="soft",
),
rx.text(item, font_size="1.25em"),
),
Expand All @@ -125,7 +145,7 @@ def todo_example():
rx.input(
on_blur=ListState.set_new_item, placeholder="Add a todo...", bg="white"
),
rx.button("Add", on_click=ListState.add_item, bg="white"),
rx.button("Add", on_click=ListState.add_item),
rx.divider(),
rx.list.ordered(
rx.foreach(
Expand All @@ -142,20 +162,17 @@ def todo_example():

## Dictionaries

Items in a dictionary can be accessed as list of key-value pairs.
Items in a dictionary are passed to the render function as key-value pairs.
Using the color example, we can slightly modify the code to use dicts as shown below.

```python demo exec
from typing import List


class SimpleDictForeachState(rx.State):
color_chart: dict[int, str] = {1: "blue", 2: "red", 3: "green"}
color_chart: dict[int, str] = {1: "#3E63DD", 2: "#E5484D", 3: "#12A594"}


def display_color(color: List):
# color is presented as a list key-value pair([1, "blue"],[2, "red"], [3, "green"])
return rx.box(rx.text(color[0]), bg=color[1])
def display_color(color: rx.Var[tuple[int, str]]):
Comment thread
masenf marked this conversation as resolved.
Outdated
# color is presented as a key-value pair such as (1, "#3E63DD").
return color_swatch(color[0], color[1])


def foreach_dict_example():
Expand All @@ -165,31 +182,38 @@ def foreach_dict_example():
```

Now let's show a more complex example with dicts using the color example.
Assuming we want to display a dictionary of secondary colors as keys and their constituent primary colors as values, we can modify the code as below:
This example groups related hex colors in a dictionary and renders both the keys and values as swatches:

```python demo exec
from typing import List, Dict


class ComplexDictForeachState(rx.State):
color_chart: Dict[str, List[str]] = {
"purple": ["red", "blue"],
"orange": ["yellow", "red"],
"green": ["blue", "yellow"],
"#8E4EC6": ["#E5484D", "#3E63DD"],
"#F76B15": ["#AD5700", "#E5484D"],
"#12A594": ["#3E63DD", "#AD5700"],
}


def display_colors(color: List):
def display_colors(color: rx.Var[tuple[str, list[str]]]):
return rx.vstack(
rx.text(color[0], color=color[0]),
color_swatch(color[0], color[0]),
rx.hstack(
rx.foreach(color[1], lambda x: rx.box(rx.text(x, color="black"), bg=x))
rx.foreach(
color[1],
lambda x: color_swatch(x, x),
)
),
align="center",
spacing="2",
)


def foreach_complex_dict_example():
return rx.grid(
rx.foreach(ComplexDictForeachState.color_chart, display_colors), columns="2"
rx.foreach(ComplexDictForeachState.color_chart, display_colors),
columns="3",
spacing="4",
)
```
Loading