Reflex Changelog
v0.9.6 (2026-06-25)
Features
- Auto-memoized (
rx.memo) components now compile to.web/app_components/output paths that mirror their defining Python source module (using the real package name, including framework packages) instead of being bundled into a single sharedcomponents.jsx. The compiler's auto-memo registry is scoped per source module, so identical-rendering subtrees in different modules each emit their own output instead of one silently overwriting another, hot-reloads of a module refresh the correct output, and stale memo files are cleaned up when their source changes. Memos whose module can't be mirrored (__main__, unsafe names) fall back to one file per memo at.web/utils/components/<name>.jsx. Each mirrored memo's generated export name also carries a stable per-module suffix, so two memos that share a name in different modules compile to distinct symbols and can be used together on one page without colliding. (#6457) rx._x.hybrid_propertynow works on dataclasses, pydantic models and SQLAlchemy models, not justStateclasses. Accessing the property through an object var on the frontend (e.g.State.info.a_b) renders it as a var, using the same code you already use on the backend. (#6617)reflex initnow writes a Reflex-managed section intoAGENTS.md(fetched from the canonical source and delimited by markers that preserve surrounding user content), and bridges it for Claude Code by creating aCLAUDE.mdimporting@AGENTS.md— or, if aCLAUDE.mdexists without the import, managing the section there directly. (#6620)rx._x.hybrid_propertynow raises a clear error when its frontend logic reads a backend (underscore-prefixed) state var, instead of silently baking the var's server-side default into the frontend. Reference a regular var, or provide a separate frontend implementation with@<name>.var. (#6621)
Bug Fixes
- Sync
reflex.lock/package.jsonto.web/package.jsonbefore installing packages to ensure lock file and package.json are aligned. (#6658) - Avoid re-entering config loading when a
Statesubclass is defined inrxconfig.py. (#6662) - Raise minimum dependency versions to pull in security fixes:
starlette>=1.3.1(Host-header path poisoning,request.form()DoS, and UNC-path SSRF),python-multipart>=0.0.32(quadratic-time querystring DoS, unbounded header field size, and negativeContent-Lengthbuffering inparse_form), andgranian>=2.7.4(WSGI and WebSocket header-panic DoS). (#6665) - Fixed
modify_stateto rebindEventContext.tokento the token being modified, so delta resolution and computed vars inside shared-state fan-out tasks observe the correct client token rather than the triggering event's inherited context. (#6673)
v0.9.5.post2 (2026-06-10)
Bug Fixes
- Allow access to State from
app_wrapcomponents (#6651)
v0.9.5.post1 (2026-06-10)
Bug Fixes
- Bumped minimum
reflex-components-coredependency to 0.9.5 for compatibility.
v0.9.5 (2026-06-10)
Features
rx.formon_submithandlers can now annotate their form-data parameter with aTypedDict(includingtyping_extensions.NotRequiredfields). The submitted mapping is accepted by the event-argument type checker, and at component build time the form statically validates that its controls supply every requiredTypedDictfield, raisingEventHandlerValueError— with the missing and present field names — when a required field has no control with a matching staticname/id. Validation is skipped when the form sets anid(controls may be associated externally via the HTMLformattribute) or when any control identifier is a dynamicVar. (#6301)- Event handlers attached to JSX literals built outside a component's render scope — such as an
ErrorBoundary'sonError— can now dispatch events.addEventsis reached through a module-level import thatEventLoopProviderpopulates on each render, so dispatch no longer depends on auseContexthook being hoisted into the calling scope. The state and event-loop providers, previously hard-coded in the layout template, are now injected around the app root by the compiler from theapp_wrapsdeclared on theVars that use them. (#6447) - Added
App.hydrate_fallback, a component rendered during the page's hydration window (React Router'sHydrateFallback) instead of a blank white page. It can also be configured without code through thehydrate_fallbackconfig — a dotted import path to a no-arg callable returning a component, settable via theREFLEX_HYDRATE_FALLBACKenvironment variable — with theAppargument taking precedence. Note that the fallback only covers the hydration window after the JS bundle has loaded, not the initial bundle download. (#6630) - Added the
REFLEX_HOT_RELOAD_OVERRIDE_PATHSenvironment variable, a colon-separated list of paths that, when set, fully replaces the paths watched for hot reload in dev mode — taking precedence over the config-derived defaults as well asREFLEX_HOT_RELOAD_INCLUDE_PATHSandREFLEX_HOT_RELOAD_EXCLUDE_PATHS. (#6639)
Bug Fixes
- Anonymous telemetry now reports the installation and project identifiers as UUID strings rather than 128-bit integers. PostHog coerced the large integers to floats, discarding all but ~16 significant digits and risking distinct installs or apps being correlated as one. Each identifier is re-encoded to the same value (a UUID carries the same 128 bits), and a one-time PostHog
$create_aliaslinks an installation's pre-existing history to its new identifier so continuity is preserved. (#6611) scripts/make_pyi.pyis now a proper CLI for maintainingpyi_hashes.json:--forceregenerates every default target (ignoring the incremental markers), explicit targets are merged into the registry instead of pruning it, and an unreachable last-run commit (after a branch switch or rebase) triggers a full regeneration. A new--checkmode, wired into the pre-commit CI job, fails when apyi_hashes.jsonentry no longer has a matching.pysource. (#6614)State.get_var_value()no longer silently returns a wrong value when passed a Var operation — an arithmetic/concatenation expression such asState.a + State.b, or an indexed/item access such asState.items[0]. Previously it resolved the state and field of the operation's first operand and returned that field's value instead of the operation's result. It now raisesUnretrievableVarValueError, consistent with how it already handled vars not associated with any state. Plain field and computed-var references continue to resolve as before. (#6633)
Performance
- Speed up reading mutable state vars (lists, dicts, dataclasses) through
MutableProxy. The per-element check that detectsdataclasses.asdict/astuplerecursion now readsframe.f_code.co_filenamedirectly instead of callinginspect.getfile(), cutting proxy read overhead by roughly 3-4x on large containers without changing behavior. (#6600)
Miscellaneous
- Report the versions of the first-party Reflex subpackages shipped with Reflex (
reflex-base, thereflex-components-*family andreflex-hosting-cli) in anonymous telemetry via a newreflex_package_versionfield. The set is derived from Reflex's own declared dependencies, so unrelated third-partyreflex-*packages are never reported. Now that Reflex is split across many independently-versioned packages, the singlereflex_versionfield no longer reflects the full install. (#6610)
v0.9.4 (2026-06-03)
Deprecations
rx._x.memois deprecated in favor ofrx.memo. The old name remains a working alias for now; update imports to userx.memodirectly. (#6517)@rx.memonow expects each parameter to be annotated asrx.Var[...](orrx.RestProp/rx.EventHandler) and the function to declare anrx.Componentorrx.Var[...]return type. Memos that still use bare Python types (e.g.name: str) or omit the return annotation keep working — the values are coerced torx.Var[...]/rx.Componentand a deprecation warning points at the parameters and return type that need explicit annotations — but this fallback will be removed in 1.0. (#6598)
Features
- Added
rx._x.hybrid_property, a property decorator usable on State classes that works like a normal Python property for backend access while also rendering on the frontend at class level. Use the same method for both, or register a separate frontend implementation with@<name>.var. (#3806) - Promoted the component memo system to a first-class
rx.memoAPI. Memo-decorated components now acceptrx.EventHandlerparameters and carry annotated return types so they type-check correctly at call sites. (#6517) - Added
rx.EMPTY_VAR_COMPONENT, an empty-componentrx.Var[rx.Component]sentinel for use as a default on@rx.memochildrenslots (and anyrx.Var[rx.Component]prop) — the component counterpart torx.EMPTY_VAR_STRandrx.EMPTY_VAR_INT. (#6598) @rx.memonow evaluates the decorated function body lazily — on first use (component instantiation) or at compile time — instead of at import time. This speeds up startup and lets a memo reference modules that aren't fully imported yet, sidestepping circular-import errors during decoration. Body-dependent errors (e.g. a var-returning memo that uses hooks or non-bundled imports) now surface when the memo is first used or compiled rather than at import. (#6598)
Miscellaneous
- Introduced towncrier-based changelog management. Each PR that changes package source now adds a fragment under the affected package's
news/directory; fragments are assembled intoCHANGELOG.mdat release time. See CONTRIBUTING.md for the full workflow. (#6350) - Removed the "choose templates" option from
reflex init. The interactive prompt now offers only a blank app or the AI builder, and no longer opens the open-source templates page. (#6592)