docs/library/other/memo.md
import reflex as rx
The @rx.memo decorator turns a function into a memoized React component. The compiler emits the function as its own module, and React's memo only re-renders it when its declared props change. Reach for it when a subtree is expensive to render and depends on a narrow slice of state.
Every parameter must be annotated with rx.Var[...] or rx.RestProp. The compiler reads those annotations to generate prop names, prop forwarding, and the JS function signature.
rx.Var[T] for props — annotate each prop as rx.Var[T] where T is the prop's runtime type (str, int, a TypedDict, etc.). Inside the function body, the parameter is a Var you compose into the rendered tree.rx.RestProp for spread props — at most one parameter may be annotated as rx.RestProp, which forwards unrecognized kwargs through to the rendered root.rx.Var[rx.Component] for slot children — a parameter named children annotated as rx.Var[rx.Component] accepts children rendered by the caller.Defaults need to be rx.Var values. For the common empty cases use the module-level constants rx.EMPTY_VAR_STR (an empty string) and rx.EMPTY_VAR_INT (zero): class_name: rx.Var[str] = rx.EMPTY_VAR_STR falls back to "" when the caller omits the prop.
class DemoState(rx.State):
count: int = 0
@rx.event
def increment(self):
self.count += 1
@rx.memo
def expensive_component(label: rx.Var[str]) -> rx.Component:
return rx.vstack(
rx.heading(label),
rx.text("This component only re-renders when props change."),
rx.divider(),
)
def index():
return rx.vstack(
rx.text(f"Count: {DemoState.count}"),
rx.button("Increment", on_click=DemoState.increment),
expensive_component(label="Memoized Component"),
)
expensive_component re-renders only when label changes — bumping DemoState.count does not invalidate it.
Props can be ordinary Vars. The memoized component re-renders when those Vars change:
class AppState(rx.State):
name: str = "World"
@rx.memo
def greeting(name: rx.Var[str]) -> rx.Component:
return rx.heading("Hello, " + name)
def index():
return rx.vstack(
greeting(name=AppState.name),
rx.input(value=AppState.name, on_change=AppState.set_name),
)
rx.RestPropUse rx.RestProp to accept and forward arbitrary props (think ...rest in JSX). Useful for thin wrappers that re-style a primitive without redeclaring every prop.
@rx.memo
def primary_button(
rest: rx.RestProp,
*,
label: rx.Var[str],
) -> rx.Component:
return rx.button(label, class_name="bg-primary-9 text-white", **rest)
def index():
return primary_button(
label="Save",
on_click=rx.console_log("clicked"),
id="save",
)
At most one rx.RestProp parameter is allowed per memo.
Declare a parameter named children typed as rx.Var[rx.Component] to receive a child subtree.
@rx.memo
def card(
children: rx.Var[rx.Component],
*,
title: rx.Var[str],
) -> rx.Component:
return rx.box(
rx.heading(title),
children,
class_name="border border-slate-5 rounded-lg p-4",
)
def index():
return card(
rx.text("Body copy goes here."),
title="Memoized card",
)
Var Instead of a ComponentA memo function can return rx.Var[T] instead of rx.Component. The compiler emits a plain JavaScript function and the call site is just a Var you can compose into the page.
class PriceState(rx.State):
amount: int = 100
currency: str = "USD"
@rx.memo
def format_price(amount: rx.Var[int], currency: rx.Var[str]) -> rx.Var[str]:
return currency.to(str) + ": $" + amount.to(str)
def index():
formatted = format_price(amount=PriceState.amount, currency=PriceState.currency)
return rx.vstack(
rx.text(formatted),
)
The body of a Var-returning memo runs at compile time and is restricted to Var operations — no hooks, no Python branching on the Vars.
Reach for rx.memo when:
Skip it when:
rx.memoThe previous rx.memo accepted plain-typed arguments (def card(title: str)). The new one requires rx.Var[...]. To migrate:
# Before
@rx.memo
def card(title: str) -> rx.Component: ...
# After
@rx.memo
def card(title: rx.Var[str]) -> rx.Component: ...
The old rx._x.memo alias still resolves to the new memo and prints a one-time was promoted to rx.memo notice.
rx.memorx.memo(component_fn)
Wraps a function whose parameters are all rx.Var[...] or rx.RestProp. Returns a callable that constructs the memoized component (or a Var if the function's return annotation is rx.Var[T]).
| Argument | Type | Description |
|---|---|---|
component_fn | Callable[..., rx.Component | rx.Var] | The function to memoize. All parameters must be rx.Var[...] or rx.RestProp. |