How should I handle rx.foreach when working with pandas?

Hi guys!

Discovered Reflex a few days ago and I’m absolutely engaged! I hope I’m not making some stupid questions, but I’m struggling a little with the rx.foreach.

I’m trying to emulate some of the components used in the dashboard template, but cannot seem to integrate my view with a for each.

My goal:

I have a dataframe, that I want to filter to get the top greatest / least 5 rows of some kind of property.

When I have those, I want to create an item(), for each, and get them all into the adquisition(). I don’t want to go 1 by 1, just use the for each.

I process the dataframe, and get this dict structure:

class TopGreatestEntry(TypedDict):
    province: str
    progress: int
    color: str

[{'province': 'Málaga', 'progress': 325, 'color': 'red'},
 {'province': 'Santa Cruz de Tenerife', 'progress': 219, 'color': 'green'},
 {'province': 'Baleares', 'progress': 213, 'color': 'blue'},
 {'province': 'Araba', 'progress': 161, 'color': 'orange'},
 {'province': 'Palencia', 'progress': 152, 'color': 'purple'}]


I created the top_greatest_topic_1 like this:

top_greatest_topic_1: List[TopGreatestEntry] = []

Then, I’ll try to create this items:

def item(province: str, progress: int, color: str) -> rx.Component:
    return (
        rx.hstack(
            rx.flex(
                rx.text(
                    f"{province}  {progress}%",
                    position="absolute",
                    top="50%",
                    left=["90%", "90%", "90%", "90%", "95%"],
                    transform="translate(-50%, -50%)",
                    size="1",
                ),
                rx.progress(
                    value=progress,
                    height="19px",
                    color_scheme=color,
                    width="100%",
                ),
                position="relative",
                width="100%",
            ),
            width="100%",
            border_radius="10px",
            align="center",
            justify="between",
        ),
    )

def adquisition() -> rx.Component:
    return rx.vstack(
        rx.foreach(
            StatsState.top_greatest_topic_1,
            lambda row, index: item(
                province=str(row["province"]),  
                progress=int(float(row["progress"])),  
                color=str(row["color"]),
            ),
        ),
        width="100%",  
        spacing="6",   
    )


I have tried this in many ways. Casting or not the item args before passing them, using a lambda or not, tried with lists, with tuples, with dicts.

Somehow, I always end up here:

TypeError: int() argument must be a string, a bytes-like object or a real number, not 'ObjectItemOperation'

Any help on how should I overcome this is so much appreciated. I’ve been reading this a lot Foreach and yet not understood what I’m doing wrong.

Thanks in advance guys!!

from typing import TypedDict
import reflex as rx

class TopGreatestEntry(TypedDict):
    province: str
    progress: int
    color: str

class State(rx.State):
    top_greatest_topic_1: list[TopGreatestEntry] = [
        {'province': 'Málaga', 'progress': 325, 'color': 'red'},
        {'province': 'Santa Cruz de Tenerife', 'progress': 219, 'color': 'green'},
        {'province': 'Baleares', 'progress': 213, 'color': 'blue'},
        {'province': 'Araba', 'progress': 161, 'color': 'orange'},
        {'province': 'Palencia', 'progress': 152, 'color': 'purple'}
    ]


def item(province: str | rx.Var[str], progress: int | rx.Var[int], color: str | rx.Var[str]) -> rx.Component:
    progress = rx.Var.create(progress).to(float).to(int) # not sure why this casted to a float and later to an int in the original
    return rx.hstack(
            rx.flex(
                rx.text(
                    f"{province}  {progress}%",
                    position="absolute",
                    top="50%",
                    left=["90%", "90%", "90%", "90%", "95%"],
                    transform="translate(-50%, -50%)",
                    size="1",
                ),
                rx.progress(
                    value=progress,
                    height="19px",
                    color_scheme=rx.Var.create(color).to(str),
                    width="100%",
                ),
                position="relative",
                width="100%",
            ),
            width="100%",
            border_radius="10px",
            align="center",
            justify="between",
        )


def index() -> rx.Component:
    return rx.vstack(
        rx.foreach(
            State.top_greatest_topic_1,
            lambda row: item(
                province=row["province"],
                progress=row["progress"],
                color=row["color"],
            ),
        ),
        width="100%",
        spacing="6",
    )

app = rx.App()
app.add_page(index)

I think this should actually work. Foreach is typically used with State Vars, which means all other types are casted to Vars at this point. the int type expects a simple type like str when casting, so this fails since what’s technically being casted is not a supported type at that point.

This was definitely so helpful Elijah.

Thank you so much! It worked like a charm!