Understanding on_click event in foreach component

Hello everyone, I’m just starting to use relfex and probably understand something wrong in the event handling.
What i want to achieve is basically having a list of clickable items (e.g. buttons) that behave different depending on which button was clicked. But since the list may contain a lot of elements i dont want to write one event handler per button.
I tried to solve it myself by going through examples but couldn’t make it work so here is my minimal example:

import reflex as rx

class State(rx.State):
    data = ["a", "b", "c", "d"]

def draw_button(name: str) -> rx.Component:
    return rx.button(name, on_click=rx.toast(name))

def index() -> rx.Component:
    return rx.foreach(
        State.data,
        draw_button
    )

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

What i expected to happen was to see 4 buttons with different label (a,b,c,d), that on click cause a different toast (a,b,c,d).
Instead when running the app I get:

“reflex.utils.exceptions.VarTypeError: Cannot convert Var ‘(name === “”)’ to bool for use with if, and, or, and not. Instead use rx.cond and bitwise operators & (and), | (or), ~ (invert).”

When testing it with a constant string in the rx.toast() function it worked fine.

Thanks in advance for any help.

I think the issue here is with the toast component not happy with the var being passed. It takes in a str literal. You can do something like this as a workaround:

class State(rx.State):
    data = ["a", "b", "c", "d"]

    def print_toast_msg(self, name: str):
        yield rx.toast(name)


def draw_button(name: str) -> rx.Component:

    return rx.button(name, on_click=State.print_toast_msg(name))


def index() -> rx.Component:
    return rx.container(
        rx.foreach(
            State.data,
            lambda name: draw_button(name)
        )
    )


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

I opened a PR to fix this in a future release Handle Var passed to `rx.toast` by masenf · Pull Request #4405 · reflex-dev/reflex · GitHub

In the meantime, you can also use rx.toast(title=name) which will bypass the check and work with foreach vars (for example, if you did not want to define an event handler in the state)