Tiempo 1:25–2:10
En esta lección guardaremos los datos de los clientes en el State y haremos que la tabla y la insignia se dibujen a partir de esos datos. Es el momento de aprender el concepto más importante de Reflex: la Var.
import dataclasses
@dataclasses.dataclass
class User:
name: str
email: str
gender: strUser(name="...", email="...", gender="...").{"name": ...}), pero con un dataclass el editor detecta las erratas al escribir los nombres de los campos, y en el código de pantalla puedes acceder con un punto, como user.name.class State(rx.State):
users: list[User] = [
User(name="Danilo Sousa", email="danilo@example.com", gender="Male"),
User(name="Zahra Ambessa", email="zahra@example.com", gender="Female"),
]rx.State se convierten en variables de estado (state vars). El valor que escribes aquí es el valor inicial.: list[User]) es obligatoria. Reflex se fija en el tipo para decidir en qué formato (JSON) enviarlo al navegador y qué métodos se pueden usar.En la lección 1 dijimos que "las funciones de pantalla solo se ejecutan una vez, al arrancar la app". Entonces, ¿qué obtienes si usas State.users dentro de una función de pantalla? Si lo imprimes, verás esto:
>>> type(State.users).__name__
'ArrayCastedVar'
>>> print(State.users.length())
reflex___state____state__tutorial_261019___tutorial_261019____state.users_rx_state_.lengthNo sale la lista de clientes, sino una expresión de JavaScript. Eso es una Var. Cuando se ejecuta la función de pantalla todavía no hay ni usuarios ni datos, así que lo único que se crea es una promesa: "más adelante, lee este valor en el navegador".
Por eso hay parte de la sintaxis de Python que no se puede usar con Vars. Estos son los errores reales que da Reflex 0.10 y sus alternativas:
| Lo que quieres hacer | Código que no funciona | Error que aparece | A la manera de Reflex |
|---|---|---|---|
| Contar elementos | len(State.users) | TypeError: object of type 'ArrayCastedVar' has no len() | State.users.length() |
| Condicional | "a" if State.n > 1 else "b" | VarTypeError: Cannot convert Var ... to bool | rx.cond(State.n > 1, "a", "b") |
| Bucle | for u in State.users: | VarTypeError: Cannot iterate over Var ... | rx.foreach(State.users, show_user) |
| Transformaciones complejas | Calcular dentro de la función de pantalla | — | Calcular en un evento o en un @rx.var (computed var) |
En cambio, las comparaciones y operaciones aritméticas entre Vars (State.page + 1) o meter una Var en un f-string (f"Total: {State.total} clientes") funcionan sin problema, porque la propia operación se traduce a una expresión de JavaScript.
Nota para el instructor — Esta tabla es lo más importante del curso. La mayoría de los errores con los que se topa quien empieza con Reflex salen de aquí. En el vídeo, te recomendamos escribir len(State.users) a propósito para enseñar la pantalla de error, preguntar "¿por qué no funciona?" y responder con el resultado del print de arriba.
Ahora cambia la insignia provisional de la cabecera por el número real de clientes.
rx.badge(
State.users.length(), # una Var en lugar de "2"
variant="soft",
color_scheme="gray",
radius="full",
),def show_user(user: User):
return rx.table.row(
rx.table.cell(user.name),
rx.table.cell(user.email),
rx.table.cell(user.gender),
style={"_hover": {"bg": rx.color("gray", 3)}},
align="center",
)User, lo que llega en realidad es una Var que apunta a un User. user.name también se convierte en una expresión: "lee el name del cliente de esta fila". El acceso con punto funciona gracias a que declaramos los campos con un dataclass.style={"_hover": {...}} es el estilo que se aplica al pasar el ratón por encima. Las claves que empiezan por _, como _hover o _focus, son selectores de estado como :hover en CSS.Debajo de la cabecera, añade la tabla dentro de la tarjeta como segundo hijo.
rx.box(
rx.table.root(
rx.table.header(
rx.table.row(
rx.table.column_header_cell("Name"),
rx.table.column_header_cell("Email"),
rx.table.column_header_cell("Gender"),
)
),
rx.table.body(rx.foreach(State.users, show_user)),
variant="ghost",
size="3",
width="100%",
),
overflow_x="auto", # desplazamiento horizontal en pantallas estrechas
width="100%",
border_top=f"1px solid {rx.color('slate', 4)}",
border_bottom=f"1px solid {rx.color('slate', 4)}",
padding_x="12px",
),root > header (fila de títulos) + body (filas de datos) > row > cell. Equivalen a <table>, <thead>, <tbody>, <tr> y <td> en HTML.rx.foreach(Var de lista, función) aplica la función a cada elemento de la lista en el navegador. La función se pasa sin llamarla, solo por su nombre (show_user, no show_user()).for de Python, porque sus valores ya se conocen en tiempo de compilación. Ejemplo: *[rx.table.column_header_cell(h) for h in ["Name", "Email", "Gender"]]Compruébalo en el navegador — Dentro de la tarjeta aparece una tabla con 2 clientes, y el 2 de la insignia ahora viene de State.users.length(). Al pasar el ratón sobre una fila, el fondo se vuelve gris claro.
localhost:3000
Vista previaYour customer directory and audience breakdown.
rx.cond para que, si hay 0 clientes, se muestre "Todavía no hay clientes" en lugar de la tabla. Pista: rx.cond(State.users.length() > 0, tabla, rx.text(...))len(State.users) a propósito y lee tú mismo el mensaje de error.len/if/for.rx.foreach hay que pasarle la función sin llamarla.← Anterior
Lección 2 · Dibujar la pantalla con componentes
Siguiente →
Lección 4 · Eventos y formularios: añadir clientes
Recibe avisos de nuevas lecciones
Te avisaremos por correo cuando este curso tenga lecciones nuevas o se abra un curso de continuación.
R
ReflexKR
Aprende Python y Reflex haciendo. Todos los ejemplos se ejecutaron y verificaron en Reflex 0.10.0.
ReflexKR es gratis y sin banners publicitarios. Si te ayudó, puedes apoyarlo con un café. ☕ Invítanos un café
Aviso de afiliados© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Preguntas y respuestas
Pregunta lo que quieras sobre esta lección. Aquí se reúnen las preguntas de todas las versiones de idioma de esta página.