Latest Results
rx.memo fixes to retain more API surface from the previous implementation (#6598)
* feat(memo): coerce legacy bare-type @rx.memo params with deprecation warning
Older @rx.memo code (the old custom_component) annotated parameters with
bare Python types (e.g. `name: str`) and omitted return annotations. The
new rx.memo required rx.Var[...]-typed params and hard-errored otherwise,
breaking that code.
Coerce bare-type params into rx.Var[...] (children -> rx.Var[rx.Component])
in the public decorator path and flag them so the existing single
deprecation warning points the user at the parameters and return type that
still need explicit annotations. Strict-mode internal callers keep raising.
Adds a deprecation news fragment.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* perf(memo): defer @rx.memo body evaluation to first use
The decorator no longer runs the decorated function body at import time.
memo() now does only signature-level work (return-annotation check, param
analysis, deprecation warning, registration) and stores a placeholder body
with _evaluated=False. The body is compiled lazily on first access via
_ensure_definition_evaluated, triggered by the component wrapper at
instantiation or by the compiler (get_component/get_function).
This speeds up import and lets a memo reference modules that aren't fully
imported yet, sidestepping circular-import ordering issues during
decoration. Body-dependent validation (hooks, non-bundled imports, "must
return a component") now surfaces at first use/compile instead of import.
Drop _bind_self_reference: recursion now resolves naturally because the
decorated name is bound by first use, and the _evaluating re-entrancy guard
covers in-eval recursion. The missing-return deprecation hint is now a
constant `-> rx.Component`, removing the body-eval-dependent return-type
inference (and its namespace-resolution helpers) so the warning stays eager.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(memo): add rx.EMPTY_VAR_COMPONENT default for component slots
Adds an empty-component `rx.Var[rx.Component]` sentinel, the component
counterpart to EMPTY_VAR_STR / EMPTY_VAR_INT, for use as a default on
`@rx.memo` `children` slots and other `rx.Var[rx.Component]` props.
It is defined in `reflex_base.components.memo` rather than `component.py`:
materializing a component var eagerly imports `Bare` (and thus
`reflex_base.environment`), so defining it in the always-early `component.py`
cycles when `environment` is the import entry point. `memo.py` is imported
lazily, after `environment` is ready. Exposed as `rx.EMPTY_VAR_COMPONENT`,
documented in the memo docs, and used by the internal skeleton component.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(memo): keep legacy base props (key, id, ...) working on @rx.memo
The legacy custom-component @rx.memo accepted base Component props
directly on the wrapper — notably `key`, needed when memos are used
under rx.foreach. A RestProp-less memo now forwards key/id/class_name/
style/custom_attrs/ref to the rendered component (with a deprecation
warning pointing at rx.RestProp) instead of raising. Identity/internal
fields (tag, library, event_triggers, ...) stay rejected since
overriding them would corrupt the render.
* refactor(memo): extract memo lazy-body evaluation into _LazyBody
Replace the per-definition _evaluated/_evaluating flags and the shared
_ensure_definition_evaluated routine with a dedicated _LazyBody generic
that owns deferral, caching, and the re-entrancy guard. MemoDefinition
now exposes `.component` / `.function` as plain properties instead of
get_component() / get_function() methods, so callers read a value rather
than invoke an evaluation step. A placeholder-less re-entrant read now
raises instead of silently returning a stale body, surfacing broken
invariants loudly.
* fix(memo): unwrap Optional from None-defaulted params on Python <=3.10
Python <=3.10's get_type_hints rewrites a `param: X = None` annotation
into Optional[X], hiding the real type from the param classifiers — so
an EventHandler param with a None default slipped past validation on
3.10 instead of being rejected. Strip the Optional wrapper before
classifying, gated behind a version check so 3.11+ skips the extra
get_origin work it doesn't need.
* chore(memo): move deprecation news fragment into reflex-base package
The base-prop passthrough deprecation lives in reflex-base, so its news
fragment belongs alongside that package rather than in the repo-root
news directory.
* chore: number memo news fragments for #6598
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* update pyi_hashes again
* fix(memo): only forward `key` without RestProp, reject silently-dropped props
Other base props (id, class_name, style, custom_attrs, ref) never reach
the rendered root without a `...rest` spread, so accepting them just
dropped them silently. Reject them with a message pointing at
`rx.RestProp`; `key` stays forwardable since React reads it at the
reconciliation layer. Gate the deprecation warning per-wrapper so a
keyed memo under `rx.foreach` doesn't re-walk the call stack per row.
* handle null str in `Var.to_string(json=False)`
* better support for `RestProp.merge` operation
allow RestProp values to be updated with other dict/objectvar values and still
conveniently function as a RestProp.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Farhan Ali Raza <farhanalirazaazeemi@gmail.com>
Co-authored-by: Farhan Ali Raza <62690310+FarhanAliRaza@users.noreply.github.com> Latest Branches
0%
claude/gracious-johnson-6FlzO 0%
0%
FarhanAliRaza:lighthouse-pr4-pr5 © 2026 CodSpeed Technology