> For AI agents: the complete documentation index is at [llms.txt](https://reflex.dev/docs/llms.txt). For a Markdown version, remove the trailing slash from the page URL and append `.md`. The docs home is available at [index.md](http://localhost:3000/docs/index.md).

## v0.9.12 (2026-09-21)

### Features

- Add `rx.vars.use_hook_var()` to create a `Var` bound to the value of a no-argument React hook imported from a given library, and `rx.vars.use_id()` to get React's stable `useId` value for the rendered component. ([#6708](https://github.com/reflex-dev/reflex/issues/6708))
- Python 3.15 has provisional support and is tested in CI. Upstream dependency limitations remain, including dill-based function serialization, which affects some persisted state and dynamic components with Redis. ([#6930](https://github.com/reflex-dev/reflex/issues/6930))
- `VarData` now tracks every state field a var is built from in `field_dependencies`, a mapping of state name to that state's field names, unioned and deduped as vars merge. A computed var depending on a composite var (`deps=[SomeState.composite]`) is now invalidated when any of its underlying fields changes — including fields belonging to a different state, which previously went untracked. `state` and `field_name` still report the first state and its first field, so existing readers are unaffected; read `field_dependencies` when you need every state a var reaches. ([#7068](https://github.com/reflex-dev/reflex/issues/7068))
- Add `BaseVarShadowsInheritedVarError`, raised when a substate declares a var that shadows a var inherited from a parent state. ([#7077](https://github.com/reflex-dev/reflex/issues/7077))
- Add native image cells to `rx.data_editor` with `type="image"`, allowing image thumbnails and text to appear together in the same grid. ([#7081](https://github.com/reflex-dev/reflex/issues/7081))
- `EnvVar` reads `timedelta` values as a number of seconds, or with a `us`, `ms`, `s`, `m`, `h` or `d` suffix. ([#7131](https://github.com/reflex-dev/reflex/issues/7131))

### Bug Fixes

- Automatically memoized components now preserve parent-provided props, event handlers, styles, and refs, allowing them to work correctly with Radix `as_child` wrappers. ([#6850](https://github.com/reflex-dev/reflex/issues/6850))
- Fix hooks and imports being silently dropped from the compiled output when two
  vars with the same value but different metadata were interpolated into the same
  f-string. Var hashing is now derived from the same identity `Var.equals` uses,
  which also fixes `Var.equals` raising `VarTypeError` for vars that carry
  dependencies, and makes `NumberVar` and `BooleanVar` hashable. ([#7015](https://github.com/reflex-dev/reflex/issues/7015))
- Preserve SQLModel relationships, ObjectVar field access, and optional serializer overrides on cold startup, including classes without module names and multiple optional-library bases. Avoid import-order failures, fork hangs, and registry corruption during serializer lookup. ([#7049](https://github.com/reflex-dev/reflex/issues/7049))
- Keep the project-local modules imported by `rxconfig.py` when the config is reloaded from the same project root, so classes they define are not duplicated and states are not registered twice. ([#7075](https://github.com/reflex-dev/reflex/issues/7075))
- Use the standard sitemap XML namespace and include `frontend_path` in default sitemap URLs. ([#7078](https://github.com/reflex-dev/reflex/issues/7078))
- Load `rxconfig` only from the requested project directory, preventing an installed or editable app from supplying another project's configuration when no local config exists. ([#7078](https://github.com/reflex-dev/reflex/issues/7078))
- Generated `.pyi` stubs now type a prop declared as a union — `content: Var[str] | Component`, say — as optional, matching the `None` default that `create()` gives every prop. Type checkers previously reported the generated signature itself as an error. ([#7080](https://github.com/reflex-dev/reflex/issues/7080))
- Persist the bundled-library registry used by backend-only workers when serializing state hydration data. ([#7096](https://github.com/reflex-dev/reflex/issues/7096))
- An `AttributeError` raised while computing a var, such as a typo inside an `@rx.serializer`, is now re-raised as a `ReflexRuntimeError` chained to the original error instead of a misleading `Attribute _cached_var_name not found` error. ([#7115](https://github.com/reflex-dev/reflex/issues/7115))
- Fix `RecursionError: maximum recursion depth exceeded` in the event processor when a handler re-chains itself many times (for example a polling loop started from `on_load`), which surfaced on the client's next navigation and in the event cleanup callbacks. ([#7145](https://github.com/reflex-dev/reflex/issues/7145))
- Consolidate deprecation warnings behind the shared logging pipeline while preserving the public `console.deprecate` API. ([#7152](https://github.com/reflex-dev/reflex/issues/7152))
- Flush OpenTelemetry compile spans before the isolated initial development compile worker exits. ([#7155](https://github.com/reflex-dev/reflex/issues/7155))
- Fix client-side event routing for events queued from callbacks (e.g. a `rx.call_script` callback or toast action triggering an upload handler): the client handler name was passed in the `event_actions` slot, so handlers like `uploadFiles` never ran. ([#7156](https://github.com/reflex-dev/reflex/issues/7156))
- Fix `ReferenceError: queueEvents is not defined` when a callback formatted for a JS interface (e.g. a toast action button) runs outside the event-loop eval context; such callbacks now dispatch through `addEvents` like compiled event triggers. ([#7157](https://github.com/reflex-dev/reflex/issues/7157))
- The upload helper no longer imports `json5`, completing the frontend dependency removal started in 0.9.2. Exported production bundles no longer embed json5's bundled core-js 2.6.5 runtime, and upload responses are now parsed with the same native JSON path the socket already uses, non-finite float values included. ([#7165](https://github.com/reflex-dev/reflex/issues/7165))
- Superseding event handlers (`@rx.event(supersedes=True)`) now cancel stale invocations across distinct event chains: supersession is ordered by the user-initiated root enqueue, so the newest chain wins, invocations within one chain (self-chains and sibling fan-out) coexist, and a stale chain enqueuing a superseding handler after a newer chain already has is dropped instead of cancelling the newer work. ([#7168](https://github.com/reflex-dev/reflex/issues/7168))
- Fix `@rx.memo` components dropping the app wraps their body requires. Providers
  requested by a nested child, or through var data as `rx.upload`'s
  `UploadFilesProvider` is, now reach the app root — so a provider-backed
  component behaves the same inside a memo as inlined into the page. ([#7176](https://github.com/reflex-dev/reflex/issues/7176))
- `Annotated[...]` hints now resolve to the type they annotate wherever Reflex inspects a type. A var typed with a pydantic discriminated union — `Annotated[Cat | Dog, Field(discriminator="kind")]` — no longer raises `Unsupported type ... for guess_type.` when read out of a state var, and its attributes resolve through the union as usual. ([#7189](https://github.com/reflex-dev/reflex/issues/7189))
- Bumped react-router to 8.4.0. ([#7202](https://github.com/reflex-dev/reflex/issues/7202))
- `BaseStateMeta` validates the declarations of every class descending from a state declared with `state_root=True` (`reflex`'s `BaseState`), so `reflex` no longer needs a `BaseStateMeta` subclass as the metaclass of its states and a third-party metaclass derived from `BaseStateMeta` composes with state classes again. ([#7215](https://github.com/reflex-dev/reflex/issues/7215))
- An `@rx.var(cache=False)` value only counts as sent to the client once the delta carrying it is delivered, so a value a `get_delta` override withholds is sent as soon as the override releases it instead of being deduplicated away until it changes again. ([#7216](https://github.com/reflex-dev/reflex/issues/7216))

### Performance

- Components that read the color mode or event loop context no longer re-render on unrelated `ThemeProvider` updates or on router navigation. The `ThemeProvider` system-preference listener is now attached once on mount. ([#6180](https://github.com/reflex-dev/reflex/issues/6180))
- Reduce browser rendering overhead for state updates, especially in apps with many substates. ([#6181](https://github.com/reflex-dev/reflex/issues/6181))
- Lazy imports now cache resolved attributes on the package, so repeated access is a plain attribute lookup instead of a `__getattr__` round-trip. On Python 3.15+, lazy loading delegates to the interpreter's native lazy imports (PEP 810). ([#6930](https://github.com/reflex-dev/reflex/issues/6930))
- `ComputedVar` now records a key for the value an uncached (`cache=False`) var last sent to each client, so `BaseState.get_delta` can leave the var out of the delta when a recomputation produces the same value. ([#6946](https://github.com/reflex-dev/reflex/issues/6946))
- Load pandas, Plotly, and Pillow serializers on demand and avoid importing SQLAlchemy for generic type helpers, reducing startup time and memory when these integrations are unused. ([#7049](https://github.com/reflex-dev/reflex/issues/7049))
- The event processor now refreshes only the router vars whose backing `router_data` keys actually changed, so a navigation no longer rebuilds and re-sends the connection-scoped session and header data. `ROUTER_VARS` names the per-field router vars that replaced the single `router` var on the root state. ([#7068](https://github.com/reflex-dev/reflex/issues/7068))
- Add the opt-in `frontend_lazy_bundled_libraries` config setting to load optional dynamic-component libraries on first use, reducing JavaScript loaded by ordinary pages. React and the shared runtime remain immediately available. ([#7078](https://github.com/reflex-dev/reflex/issues/7078))
- Allow unused memoized components to be removed from shared frontend bundles. Render readable code before Shiki loads, and highlight blocks as they approach the viewport. Changed highlighting options immediately restore the readable fallback until new highlighting succeeds. ([#7078](https://github.com/reflex-dev/reflex/issues/7078))
- Speed up compilation by reading only the props a component sets, caching literal Var dispatch by value type, and trimming render and app-wrap bookkeeping. Tags now render through `render(children)`: `CommonTag` holds the generic protocol shared by every tag class, and `Tag` overrides it with a direct fast path. ([#7121](https://github.com/reflex-dev/reflex/issues/7121))
- Share one event chain per handler and trigger across call sites, and reuse memoized event wrappers by chain identity during compilation. ([#7122](https://github.com/reflex-dev/reflex/issues/7122))
- Var operations no longer keep a permanent reference to every operand they are built from, fixing a memory leak that grew with each operation an app created, and building them is 1.5x to 3.8x faster depending on the operation. ([#7198](https://github.com/reflex-dev/reflex/issues/7198))

### Miscellaneous

- Route log records from the new `reflex-build-sdk` package through the Reflex logger, so they follow the configured log level and sinks. ([#7166](https://github.com/reflex-dev/reflex/issues/7166))


## v0.9.11 (2026-09-11)

### Breaking Changes

- Bundled Bun moves to 1.4.0, and the minimum supported Bun version rises to 1.4.0 with it. Bun 1.4 creates new lockfiles at `lockfileVersion: 2`, which Bun 1.3.x cannot parse at all — so once a project's `reflex.lock/bun.lock` has been generated under 1.4, everyone building it (teammates, CI, Docker images) needs Bun 1.4 too. An existing `lockfileVersion: 1` lockfile is kept at v1 by Bun 1.4, even across dependency changes, so already-initialized projects are unaffected until their lockfile is regenerated from scratch. Reflex installs and manages its own Bun, so this only needs action if you point `bun_path` at your own Bun or rely on one from `PATH`. ([#7019](https://github.com/reflex-dev/reflex/issues/7019))

### Deprecations

- `reflex_base.config._load_config()` is deprecated in favor of `_get_config()`; use `get_config()` to read the cached config. ([#6933](https://github.com/reflex-dev/reflex/issues/6933))

### Features

- Add inert OpenTelemetry trace points and metrics around event handler execution, state acquisition, socket messages and compile stages (`reflex_base.otel`) and `window.__reflex_otel` hooks in the frontend event loop and upload helper; they cost one boolean check, and import nothing from `opentelemetry`, until the `reflex-otel` package enables them (`reflex-base` itself does not depend on `opentelemetry-api`). ([#6227](https://github.com/reflex-dev/reflex/issues/6227))
- `hybrid_property` remains a `property` subclass at runtime, but type checkers now resolve class-level access to the frontend var's type instead of the descriptor: without a var function it follows the var equivalent of the getter's return type, and a var function may declare a type of its own. The var function may be a `classmethod` or `staticmethod`, may return `None` to declare that the property has no frontend value on a class, and — like `getter`, `setter` and `deleter` — may be defined under a name of its own instead of shadowing the property's declaration. ([#6812](https://github.com/reflex-dev/reflex/issues/6812))
- `reflex_base.utils.log.reserve_stdout()` reserves stdout for a machine-readable document, rendering log records, tables, rules, prompts, spinners and progress bars to stderr for as long as it is set. ([#6917](https://github.com/reflex-dev/reflex/issues/6917))

### Bug Fixes

- A hybrid property a state inherits from a base class is no longer shadowed by state storage when the state annotates its name, which made such a state fail to instantiate. ([#6812](https://github.com/reflex-dev/reflex/issues/6812))
- Attribute probes on vars (e.g. `inspect.iscoroutinefunction` via `unittest.mock`) no longer trigger ForwardRef resolution of unrelated annotations, silencing spurious "Failed to resolve ForwardRefs" warnings and avoiding `NameError` under PEP 649 lazy annotations on Python 3.14. ([#6929](https://github.com/reflex-dev/reflex/issues/6929))
- Avoid ModuleNotFoundError when loading `rxconfig.py` in a multi-threaded context. ([#6933](https://github.com/reflex-dev/reflex/issues/6933))
- Auto-memoized components that render identically no longer share a generated memo name, which silently dropped one of the two compiled bodies. The name now accounts for:

  - module-level code emitted by `add_custom_code`
  - dynamic imports
  - app-wrap components, including `rx.text` and the other `MarkdownComponentMap` components that all hashed alike
  - the defining module, so same-named components from different modules stay apart
  - the identity of dataclasses and enum members, which previously hashed by shape and by `str()`

  ([#6947](https://github.com/reflex-dev/reflex/issues/6947))
- The compatibility delta flush for background handlers that never enter `async with self` now also runs when the handler raises, so uncached computed vars and preamble-dirty vars (like `router_data`) reach the client regardless of how the task ended. The exception still propagates to the backend exception handler afterwards; if the flush itself fails in that case, the flush error is logged instead of masking the handler's exception. ([#6995](https://github.com/reflex-dev/reflex/issues/6995))
- `rx.Config` now rejects a `frontend_path` whose segments are not plain directory names (`..`, backslashes, or drive letters), which would otherwise relocate the production build output outside of `.web/build/client`. ([#7044](https://github.com/reflex-dev/reflex/issues/7044))
- Fix the Safari dev-server cache-busting plugin rendering pages as comma-separated byte values with React Router 8. The rewritten HTML now streams through instead of being buffered, and multibyte characters split across response chunks stay intact. ([#7048](https://github.com/reflex-dev/reflex/issues/7048))
- Keep the frontend runtime stable across hot updates in `reflex run`. React contexts, event dispatchers, and element refs now survive a recompile, and the state and event-loop providers are no longer remounted on every compile, so a component refreshed before its provider no longer crashes with `Cannot read properties of null`, drops events, or reconnects the websocket. ([#7071](https://github.com/reflex-dev/reflex/issues/7071))
- Fix the post-eviction rehydrate fallback not running under `StateManagerRedis`. ([#7072](https://github.com/reflex-dev/reflex/issues/7072))
- Prevent runaway page-load event chains when backend-initiated events encounter expired state. ([#7073](https://github.com/reflex-dev/reflex/issues/7073))
- Reject `frontend_path` segments with trailing dots or spaces that Windows trims, and empty segments from repeated slashes, before they can produce inconsistent build paths. A single leading or trailing slash remains supported. ([#7105](https://github.com/reflex-dev/reflex/issues/7105))
- Preserve class-level `hybrid_property` frontend types on Pyright 1.1.412 and later instead of resolving them to `Any`. ([#7106](https://github.com/reflex-dev/reflex/issues/7106))
- `bundle_library()` bundles subpaths without an unused package root; explicit subpath strings also work without registering the package root. ([#7109](https://github.com/reflex-dev/reflex/issues/7109))
- Passing a component to `bundle_library()` prebundles the rendered library imports of its entire tree, including children and component-valued props, before initial rendering. ([#7109](https://github.com/reflex-dev/reflex/issues/7109))
- Invalid `bundle_library()` arguments now raise a clear `TypeError` directing callers to pass a library name string or a prototype component instance. ([#7109](https://github.com/reflex-dev/reflex/issues/7109))
- Preserve default exports when dynamic components use a bundled package root as well as a subpath. ([#7109](https://github.com/reflex-dev/reflex/issues/7109))
- Keep explicit `bundle_library()` registrations across compiler resets and registration-context forks without duplicates. ([#7109](https://github.com/reflex-dev/reflex/issues/7109))

### Performance

- Component content hashing, which auto-memoization runs for every memoized component during a compile, encodes roughly 1.2-1.3x faster on large pages. Generated memo module names change as a result; nothing outside the compiled output refers to them. ([#6947](https://github.com/reflex-dev/reflex/issues/6947))
- New opt-in dev-server knobs: `REFLEX_DEV_PROD_REACT=1` serves React's production build under the Vite dev server (navigation CPU on a large app 54 → 36 ms, prod build 24 ms; edits become a full reload since Fast Refresh needs dev React), and `REFLEX_VITE_WARMUP_ROUTES=1` pre-transforms route modules at startup so the first visit to a page no longer waits on Vite (105–131 → 43–69 ms, or 20–32 ms with both). ([#7021](https://github.com/reflex-dev/reflex/issues/7021))
- Trimmed the framework overhead around every event handler: the state fast-paths its own bookkeeping attributes, foreground handler tasks start eagerly on Python 3.12+, the computed-var expiry check only looks at interval vars, route matching is memoized per path, and socket.io handlers run inline. About 28% less CPU per trivial event and 20% more events per second per worker under concurrent load. ([#7025](https://github.com/reflex-dev/reflex/issues/7025))
- Reduce CLI startup time and memory by loading compiler plugins and optional SQLAlchemy property support only when used. ([#7050](https://github.com/reflex-dev/reflex/issues/7050))

### Miscellaneous

- Bump bundled frontend pins: react-router 8.3.1, isbot 5.2.2, postcss 8.5.26, postcss-import 17.0.0, and vite 8.2.2. postcss-import 17 requires Node 22+, which already matches the Reflex minimum. ([#7019](https://github.com/reflex-dev/reflex/issues/7019))


## v0.9.10.post1 (2026-09-01)

### Deprecations

- `reflex_base.config._load_config()` is deprecated in favor of `_get_config()`; use `get_config()` to read the cached config. ([#6933](https://github.com/reflex-dev/reflex/issues/6933))

### Bug Fixes

- Avoid ModuleNotFoundError when loading `rxconfig.py` in a multi-threaded context. ([#6933](https://github.com/reflex-dev/reflex/issues/6933))


## v0.9.10 (2026-09-01)

### Bug Fixes

- Enqueuing an event chained from a parent event that has already finished no longer raises `RuntimeError: Cannot add a child to an EventFuture that is already done.`. Such a late-chained event skips registration under the completed parent and is processed normally. ([#6801](https://github.com/reflex-dev/reflex/issues/6801))
- Compiling unchanged source twice now produces the same files. Import order came from a `set`, whose iteration order varies with `PYTHONHASHSEED`, and a library's imports were not deduplicated against themselves; both fed the content hash a memoized component is named from, so each compile renamed those components and invalidated downstream build caches for no reason. ([#7012](https://github.com/reflex-dev/reflex/issues/7012))

### Performance

- Compiling an app with many components is substantially faster. Imports are now deduplicated as they are merged rather than only at the end, so naming a memoized component no longer costs work proportional to the size of its subtree. An app with 80 routes and 42,268 components went from 263s to 48s. ([#7012](https://github.com/reflex-dev/reflex/issues/7012))


## v0.9.9.post1 (2026-09-01)

### Deprecations

- `reflex_base.config._load_config()` is deprecated in favor of `_get_config()`; use `get_config()` to read the cached config. ([#6933](https://github.com/reflex-dev/reflex/issues/6933))

### Bug Fixes

- Avoid ModuleNotFoundError when loading `rxconfig.py` in a multi-threaded context. ([#6933](https://github.com/reflex-dev/reflex/issues/6933))


## v0.9.9 (2026-08-28)

### Breaking Changes

- `get_config(reload=True)` has been replaced by `reload_config()`, and the module-level `bundled_libraries` list in `reflex_base.components.dynamic` has moved onto the active `RegistrationContext` (use `bundle_library()` / `reset_bundled_libraries()` as before). Reading `reflex_base.components.dynamic.bundled_libraries` (or `DEFAULT_BUNDLED_LIBRARIES`) still works as a deprecated shim that resolves against the active context; the shims are removed in 1.0. ([#6382](https://github.com/reflex-dev/reflex/issues/6382))
- `pydantic` is no longer a hard dependency; pydantic model support activates when it is installed. Use the `reflex-base[pydantic]` extra (or `reflex[db]`) to keep it. ([#6786](https://github.com/reflex-dev/reflex/issues/6786))
- Upgraded the frontend to React Router 8.3.0 (from 7.18.2). Its new baseline requires Node 22.22.0+, so `Node.MIN_VERSION` moves from 22.12.0 to 22.22.0; the already-pinned React 19.2.8 and Vite 8.0.16 satisfy the React 19.2.7+ and Vite 7+ floors. React Router 8 dropped the `react-router-dom` re-export package, so it is no longer installed: components that declare `library = "react-router-dom"` must import from `react-router` instead (`RouterProvider`/`HydratedRouter` come from `react-router/dom`). Existing projects have the stale entry pruned from `package.json` on the next install. ([#6854](https://github.com/reflex-dev/reflex/issues/6854))

### Deprecations

- The `console.debug/info/success/log/warn/error/timing` helpers are deprecated (removal in 1.0) but keep working as shims; use `logging.getLogger(__name__)` and the pipeline in `reflex_base.utils.log` instead. The interactive Rich features (`print`/`rule`/`status`/`ask`/`progress`) remain first-class. ([#6867](https://github.com/reflex-dev/reflex/issues/6867))
- `get_config(reload=True)` is deprecated (removal in 1.0) but keeps working: passing `reload=True` emits a deprecation warning and delegates to `reload_config()`, which forces a fresh load of the config into the current `RegistrationContext`. ([#6985](https://github.com/reflex-dev/reflex/issues/6985))

### Features

- `RegistrationContext` now carries the loaded `Config`, the registered `App`, decorated pages, and bundled libraries, and provides `fork()` to derive a fresh context that preserves existing registrations while resetting the app and config. ([#6382](https://github.com/reflex-dev/reflex/issues/6382))
- Validate incoming state deltas in the frontend before dispatching and report unprocessable updates to the backend via a new `client_error` socket event instead of failing silently in the browser console. Values reported by a client are escaped and bounded before reaching the backend logs. ([#6827](https://github.com/reflex-dev/reflex/issues/6827))
- Added `reflex_base.utils.log`: a standard python logging pipeline with a rich-rendering console handler (legacy colors preserved), a JSON-lines handler behind `REFLEX_LOG_JSON`, record deduplication, and file logging. `LogLevel` gained a correct total ordering and `to_logging_level()`, and the interactive console helpers (`print`/`rule`/`status`/`progress`) now respect JSON mode. ([#6863](https://github.com/reflex-dev/reflex/issues/6863))
- Compiled components are now named for React DevTools: memoized components take a `displayName` from the Python class or `@rx.memo` function they came from instead of showing as `Anonymous`, generated contexts are named (`StateContext(reflex___state____state.my_state).Provider` rather than an unlabelled `Context.Provider`), pages are labelled with their route (`Component(blog/[slug])`), and client-only (`NoSSRComponent`) wrappers render as `ClientSide(<Tag>)`. ([#6945](https://github.com/reflex-dev/reflex/issues/6945))
- Add the `REFLEX_REFERRER_PARAM` environment variable, read at compile time to append a `ref` query parameter to the "Built with Reflex" badge link. ([#6951](https://github.com/reflex-dev/reflex/issues/6951))

### Bug Fixes

- Event handlers marked with `@rx.event(supersedes=True)` now use latest-wins semantics: enqueuing a new invocation cancels the previous unfinished event chain for the same client token. `on_load_internal` uses this to cancel stale `on_load` chains on navigation. ([#6593](https://github.com/reflex-dev/reflex/issues/6593))
- `@rx.memo` functions that forward props through `rx.RestProp` now classify those props the same way a regular component does: a forwarded prop that is not a declared prop of the target (e.g. `font_weight=`) joins the component's `style` and renders as `css`, instead of being passed through as an unrecognized prop and silently dropped. Such props merge with an explicit `style=` rather than replacing it, and props the target actually declares are still forwarded normally. ([#6605](https://github.com/reflex-dev/reflex/issues/6605))
- Declare `rx.plugins.RadixThemesPlugin()` in the `rxconfig.py` written by `reflex init`, so freshly scaffolded apps no longer emit the implicit Radix Themes enablement deprecation warning. ([#6776](https://github.com/reflex-dev/reflex/issues/6776))
- Qualify annotations whose bare builtin name is shadowed by a member of the same class, so `Var.create` is no longer inferred as `LiteralBooleanVar` for every argument type. `Var.bool`, `BaseComponent.set` and `PropsBase.dict` shadowed `bool`, `set` and `dict` for annotations elsewhere in their own class bodies, which type checkers resolve against the class namespace. ([#6846](https://github.com/reflex-dev/reflex/issues/6846))
- The `vite preview` server that react-router prerendering fetches pages from is now pinned to `127.0.0.1`, fixing `reflex export` failing with `Prerender: Request failed for /: ECONNREFUSED` in environments where `localhost` resolves to both IPv4 and IPv6 loopback addresses (such as docker containers). ([#6857](https://github.com/reflex-dev/reflex/issues/6857))
- Resolve event handler annotations before runtime state-class patches can shadow builtin names on Python 3.14. ([#6890](https://github.com/reflex-dev/reflex/issues/6890))
- Chained events (those yielded by an event handler) now inherit the routing data of the event being processed, so `router` and dynamic route args resolve against the view that produced them instead of whichever view the last client-sent event left on the root state. ([#6919](https://github.com/reflex-dev/reflex/issues/6919))
- Stop background event handlers from computing a delta and cleaning the root state after the state lock is dropped. On a shared state tree (opportunistic locking, in-memory state manager) a concurrent foreground write landing between the background task's dirty-var snapshot and its `_clean()` was silently discarded and never reached any delta. ([#6920](https://github.com/reflex-dev/reflex/issues/6920))
- Resolve `TypeAliasType` annotations (PEP 695 `type` statements and the `typing_extensions` backport) to their underlying value in `Var.guess_type`, `_isinstance` and `typehint_issubclass`. A state var annotated with an alias like `type Key = Literal["day", "week"]` now compiles and can be assigned to, and event handlers with alias-annotated arguments can be passed uncalled to event triggers. Parameterized generic aliases (`Keys[str]` for `type Keys[T] = list[T]`) and aliases nested in unions (`Key | None`) are resolved as well. ([#6944](https://github.com/reflex-dev/reflex/issues/6944), [#6986](https://github.com/reflex-dev/reflex/issues/6986))
- The generated `vite.config.js` no longer passes options rejected or deprecated by rolldown-vite 8.x: the no-op `rollupOptions.jsx` key is dropped and `output.advancedChunks` migrated to `output.codeSplitting` (same shape), removing the "Invalid input options" and "advancedChunks option is deprecated" warnings from every prod build/export. ([#6987](https://github.com/reflex-dev/reflex/issues/6987))
- Console warnings and errors no longer print literal backslash-escaped brackets (e.g. `dict\[str, str]`). The rich-markup escapes were left over from the legacy console helpers, but the logging pipeline renders messages with markup disabled, so bracketed type names now print verbatim. `VarAttributeError` messages drop the same escapes. ([#6989](https://github.com/reflex-dev/reflex/issues/6989))
- A custom component declaring `library = "react-router-dom"` (including versioned and subpath forms) now fails compilation with an actionable error naming the component, instead of silently installing the removed package — which pulled in a second, unpinned React Router 7 copy that worked in dev by accident and broke production builds. React Router 8 dropped `react-router-dom`: use `library = "react-router"` instead, or `"react-router/dom"` for `RouterProvider`/`HydratedRouter`. ([#6991](https://github.com/reflex-dev/reflex/issues/6991))
- With `REFLEX_ENABLE_FULL_LOGGING`, granian worker records reach the log file again: the file handler now opens in append mode (truncating once up front), so it reopens after the worker's post-fork `logging.config.dictConfig` closes it instead of silently dropping every worker-side record. The legacy console file writer follows the reopened stream through a proxy, so its timestamped lines no longer leak to stdout and break `--json` output. ([#6992](https://github.com/reflex-dev/reflex/issues/6992))

### Performance

- Dev mode no longer pays for React's per-element owner-stack capture: navigation clicks in a large app dropped from ~350ms to ~83ms of main-thread CPU (5.6x prod down to ~1.3x). In exchange `React.captureOwnerStack()` returns no owner frames in dev, which affects React DevTools' owner-stack view and custom error overlays built on that API; set `REFLEX_REACT_OWNER_STACKS=1` to restore them. ([#6905](https://github.com/reflex-dev/reflex/issues/6905))
- `MemoComponent` instances no longer opt out of compiler auto-memoization wholesale. Only the passthrough wrappers the auto-memoize pass generates do, tracked by the new `auto_memo_wrapper` flag on `MemoComponentDefinition`, so state-bound props and event handlers on a `@rx.memo` call site compile their hooks into a generated wrapper instead of the enclosing page. ([#6949](https://github.com/reflex-dev/reflex/issues/6949))
- Speed up prop validation and JSON serialization on hot paths: `_isinstance` now reads `__origin__` once per type, memoizes `get_args`, and caches the deferred `Var`/`LiteralVar`/`Field` imports instead of re-importing on every call, and `json_dumps` caches its deferred `serializers.serialize` lookup. ([#6862](https://github.com/reflex-dev/reflex/issues/6862))
- `vite_config_template` declares a `resolveId` hook filter (`{ id: /react-dom\/server/ }`) on `vite-plugin-always-use-react-dom-server-node`. The plugin runs with `enforce: "pre"`, so without a filter rolldown invoked its JS handler for every import specifier in the graph (~15,800 calls on the Reflex docs build) to redirect the one specifier imported by `entry.server.node.tsx`. The template also imports `./vite-plugin-safari-cachebust.js` with its extension, which Vite's `configLoader: "native"` requires. ([#6959](https://github.com/reflex-dev/reflex/issues/6959))

### Miscellaneous

- Removed the `postcss` entry from `PackageJson.OVERRIDES`, leaving that mapping empty. `postcss` is pinned directly in `DEV_DEPENDENCIES` (8.5.23), and that top-level pin already dedupes every transitive requirer (`autoprefixer`, `postcss-import`, and `vite`'s own `^8.5.15`). Projects that already installed 0.9.8 keep an inert `"postcss": "8.5.23"` override in `reflex.lock/package.json`; it matches the dev-dependency pin and can be deleted by hand. ([#6854](https://github.com/reflex-dev/reflex/issues/6854))
- Bump bundled `vite` from 8.0.16 to 8.2.0. ([#6857](https://github.com/reflex-dev/reflex/issues/6857))
- Internal logging in reflex-base migrated from the legacy console helpers to standard python `logging` per-module loggers. ([#6864](https://github.com/reflex-dev/reflex/issues/6864))
- Property docstrings are now noun phrases rather than "Get the ..." / "Return the ..." (ruff 0.16's new `D421`). `Field.default`, `Field.default_factory` and `Field.default_value()` now admit `None`, matching what they already hold for a field whose annotated type has no computed default, and `chain_updates()` declares its `events` parameter as `Any`, matching the runtime validation it delegates to. ([#6893](https://github.com/reflex-dev/reflex/issues/6893))


## v0.9.8 (2026-08-04)

### Features

- Add `Env.PREVIEW`, the `VITE_MINIFY` and `REFLEX_NO_AUTOPREFIXER` environment variables, a `minify`/`cssMinify` option on the vite config template, and a `REFLEX_NO_AUTOPREFIXER` toggle in the generated `postcss.config.js` to support the new `preview` run mode. ([#6663](https://github.com/reflex-dev/reflex/issues/6663))
- Add a staged `Plugin.register_route` hook with `add_page` and `has_app_page` capabilities that runs once per app before its first compilation, and `rx.plugins.get_plugin()` to look up the configured plugin instance by type (raising `ConfigError` on ambiguous matches). ([#6728](https://github.com/reflex-dev/reflex/issues/6728))

### Bug Fixes

- Preserve runtime value types for unannotated `@rx.memo` component parameters. ([#6659](https://github.com/reflex-dev/reflex/issues/6659))
- Compare timezone-aware datetime Vars by their instants instead of their serialized UTC offsets. ([#6767](https://github.com/reflex-dev/reflex/issues/6767))
- In python 3.13+, the EventProcessor loop was not catching asyncio.QueueShutdown resulting in uncaught exceptions during shutdown. ([#6773](https://github.com/reflex-dev/reflex/issues/6773))
- Prevented edits to unloaded routes from poisoning React Router's browser-side HMR queue and blocking all later hot updates until a full page reload. ([#6774](https://github.com/reflex-dev/reflex/issues/6774))
- Drain queued same-token events during graceful event processor shutdown. ([#6791](https://github.com/reflex-dev/reflex/issues/6791))
- Custom attributes on a `Field` are now carried onto the rebuilt field by reference instead of deep copy, so stateful callable markers keep their identity and markers holding non-copyable values (locks, clients) no longer crash state class creation. ([#6809](https://github.com/reflex-dev/reflex/issues/6809))

### Miscellaneous

- Bumped bundled frontend dependency pins to their current releases:

  - `react` / `react-dom`: 19.2.6 → 19.2.8
  - `react-router`, `react-router-dom`, `@react-router/node`, `@react-router/dev`, `@react-router/fs-routes`: 7.15.0 → 7.18.2
  - `isbot`: 5.1.40 → 5.2.1
  - `universal-cookie`: 7.2.2 → 8.1.2
  - `postcss`: 8.5.14 → 8.5.23
  - `autoprefixer`: 10.5.0 → 10.5.4
  - `@tailwindcss/typography`: 0.5.19 → 0.5.20
  - Bun: 1.3.13 → 1.3.14

  Also raised the `rich` upper bound to `<16` (adopting rich 15). Replaced the now-redundant `cookie` `package.json` override (`universal-cookie` 8 and `react-router` resolve `cookie` to 1.x on their own) with a `postcss` override pinning it to 8.5.23 so transitive resolutions stay on a patched release (>= 8.5.18) for a security advisory.

  ([#6678](https://github.com/reflex-dev/reflex/issues/6678))
- Remove the unused `REFLEX_USE_TURBOPACK` environment variable. Turbopack is a Next.js bundler; the flag has had no effect since Reflex moved to React Router and Vite in 0.8. ([#6803](https://github.com/reflex-dev/reflex/issues/6803))


## v0.9.7 (2026-07-15)

### Deprecations

- `ArrayVar.foreach` is deprecated; use `ArrayVar.map` instead. ([#6701](https://github.com/reflex-dev/reflex/issues/6701))

### Features

- `ArrayVar` gained `map`, `filter`, `reduce`, and `flat_map` operations, and `StringVar.strip` now accepts a `chars` argument alongside new `lstrip`/`rstrip` methods. ([#6701](https://github.com/reflex-dev/reflex/issues/6701))
- Added `default_color_mode` to `rx.Config` (`"system"`, `"light"`, or `"dark"`, also settable via `REFLEX_DEFAULT_COLOR_MODE`) and moved the shared `LiteralColorMode` type and color-mode string constants into `reflex_base.constants`. This lets apps set the initial color mode without depending on the Radix themes appearance prop. ([#6716](https://github.com/reflex-dev/reflex/issues/6716))
- `@rx.memo` now accepts a `wrapper=` argument controlling the JS function that wraps the compiled component definition: keep the default React `memo`, pass a custom function `Var` (e.g. an `rx.vars.FunctionStringVar` carrying its own imports), or pass `wrapper=None` to export the bare function component. ([#6730](https://github.com/reflex-dev/reflex/issues/6730))
- Added `frozen_lockfile` to `rx.Config` (default `True`, also settable via `REFLEX_FROZEN_LOCKFILE`), controlling whether the frontend package manager runs in lockfile-enforcing mode. Reflex still creates, manages, and syncs the lockfile regardless; the option only controls whether a lockfile/`package.json` mismatch is treated as an error. ([#6763](https://github.com/reflex-dev/reflex/issues/6763))

### Bug Fixes

- Custom attributes set on a `Field` are now preserved (deep-copied) when the state metaclass rebuilds fields, instead of being silently discarded. The reserved `annotation` attribute is never carried over so rebuilt fields are not misidentified as pydantic fields. ([#6726](https://github.com/reflex-dev/reflex/issues/6726))
- Fix `_get_all_hooks_internal` mutating each component's cached internal hooks with its descendants' hooks, which made memo tag hashes order-dependent and duplicated hooks into memo bodies. ([#6741](https://github.com/reflex-dev/reflex/issues/6741))

### Performance

- Cache framework-path checks in `console.deprecate`'s call-stack walk, making repeat calls ~150x faster (deprecated attributes on hot paths, like `RouterData.page`, no longer cost multiple milliseconds per access). ([#6736](https://github.com/reflex-dev/reflex/issues/6736))
- Event chaining (`yield OtherState.handler(rows)`) no longer deep-copies payload values that are not attached to any state: only state-bound `MutableProxy` subtrees are copied, making proxy-free payloads ~5x faster to chain. ([#6739](https://github.com/reflex-dev/reflex/issues/6739))
- `Var.to()` and `Var.guess_type()` resolve their target Var subclass through cached registry lookups instead of scanning the full registry with `safe_issubclass` on every call (~70% of the cost of constructing a var operation). ([#6742](https://github.com/reflex-dev/reflex/issues/6742))


## v0.9.6.post1 (2026-06-26)

### Features

- Added the `REFLEX_EXTRA_PLUGINS` environment variable, a colon-separated list of fully qualified plugin import paths appended to the config's `plugins` list. Unlike `REFLEX_PLUGINS`, which replaces the list entirely, this preserves plugins configured in `rxconfig.py`; an entry is skipped when a plugin of the same type is already present or when its type is listed in `disable_plugins`. ([#6685](https://github.com/reflex-dev/reflex/issues/6685))

### Bug Fixes

- Stop warning when a non-built-in plugin is listed in `disable_plugins`, so config can opt out of an env-provided plugin without a spurious warning. ([#6685](https://github.com/reflex-dev/reflex/issues/6685))
- Improve error message when plugin spec from environment cannot be used. ([#6685](https://github.com/reflex-dev/reflex/issues/6685))


## v0.9.6 (2026-06-25)

### Features

- `StringVar` now includes `lstrip` and `rstrip` methods. The `strip` method now accepts an optional `chars` argument for consistency with Python’s str API. ([#5417](https://github.com/reflex-dev/reflex/issues/5417))
- Added `reflex_base.utils.memo_paths`, which translates a memo's Python source module into the mirrored `.web/app_components/` JSX path and `$/...` library specifier used by the compiler. The memo component and compiler plugin now route each memo's compiled output through these helpers so it lands alongside its source module's layout, falling back to the per-name `utils/components/<name>` path when the module can't be mirrored. The helpers also derive a per-module-unique JS symbol for each mirrored memo, and the memo registry is keyed by `(name, source module)` so same-named memos defined in different modules coexist instead of colliding. ([#6457](https://github.com/reflex-dev/reflex/issues/6457))
- `ObjectVar` attribute access now resolves `HybridProperty` descriptors defined on the underlying type, evaluating the property's frontend logic with the object var substituted as `self`. `HybridProperty` moved to `reflex_base.vars.hybrid_property` (still available as `rx._x.hybrid_property`). ([#6617](https://github.com/reflex-dev/reflex/issues/6617))
- Add `AgentsMd` constants (canonical URL, managed-section markers, and `CLAUDE.md` bridge) supporting `reflex init` AGENTS.md generation. ([#6620](https://github.com/reflex-dev/reflex/issues/6620))
- Added `HybridPropertyError`, raised when a hybrid property's frontend logic accesses a backend (underscore-prefixed) var on a state while building its frontend var. ([#6621](https://github.com/reflex-dev/reflex/issues/6621))
- `package_json_template` accepts `**additional_keys` to include extra fields (e.g. `name`, `packageManager`, `engines`) in the rendered package.json. ([#6658](https://github.com/reflex-dev/reflex/issues/6658))

### Bug Fixes

- Preserve extra bound event arguments when `rx.upload_files` is used in an upload handler. ([#5290](https://github.com/reflex-dev/reflex/issues/5290))
- Avoid re-entering config loading when a `State` subclass is defined in `rxconfig.py`. ([#6662](https://github.com/reflex-dev/reflex/issues/6662))
- Bump the bundled `vite` dev dependency to 8.0.16, fixing a `server.fs.deny` bypass on Windows alternate paths (CVE-2026-53571) in the dev server of generated apps. ([#6665](https://github.com/reflex-dev/reflex/issues/6665))
- `pyi_hashes.json` entries are now computed from the final `.pyi` content after `ruff format` / `ruff check --fix` post-processing, instead of the intermediate generator output. A pyi_generator change that only affects pre-format output no longer flags hash changes for stubs whose final content is identical.

### Miscellaneous

- `Component` gained a private `_get_tag_name()` helper returning the JS expression that references the component's tag (quoted for global-scope DOM tags without a library); `Component._render` and `DebounceInput` now share it instead of duplicating the quoting logic. ([#6637](https://github.com/reflex-dev/reflex/issues/6637))


## v0.9.5 (2026-06-10)

### Features

- Event-argument type checking now treats a mapping-style payload as compatible with a `TypedDict`-annotated callback parameter, scoped narrowly to `on_submit` triggers whose payload is a `Mapping[str, ...]` so unrelated mapping events are unaffected. Adds the `FORM_SUBMIT_MAPPING` type var (exposed on the event namespace and `pyi_generator`'s default imports) and a `Component._is_form_control` class marker that a component sets to declare it contributes a named field to form submission data. ([#6301](https://github.com/reflex-dev/reflex/issues/6301))
- `VarData` gained an `app_wraps` field so a `Var` can declare the app-level wrapper components it requires; the compiler injects them around the app root, deduped by `(priority, tag)`. This is how the state and event-loop providers now reach the React tree, since event dispatch reaches `addEvents` via a module-level import (`Imports.EVENTS`) rather than a hoisted hook. The still-reactive `connectErrors` value moves to its own `CONNECT_ERRORS` import/hook, and `Component` deep copies now drop the render cache so compile-time clones (e.g. the app-root wrapper chain) render their mutated children. ([#6447](https://github.com/reflex-dev/reflex/issues/6447))
- Added a `hydrate_fallback` config option (settable via the `REFLEX_HYDRATE_FALLBACK` environment variable), a dotted import path to a callable returning the component shown while the page is hydrating. The app root template now emits a React Router `HydrateFallback` export when a fallback is provided, and the import-path resolution shared with `extra_overlay_function` resolves nested module paths correctly. ([#6630](https://github.com/reflex-dev/reflex/issues/6630))
- Added the `REFLEX_HOT_RELOAD_OVERRIDE_PATHS` environment variable, a colon-separated list of paths that, when set, fully replaces the paths watched for hot reload in dev mode. ([#6639](https://github.com/reflex-dev/reflex/issues/6639))

### Bug Fixes

- The `reflex_base.utils.pyi_generator` build-hook entrypoint no longer rewrites `pyi_hashes.json`: it only emits the `.pyi` stubs bundled in the wheel, so building a component package (or the build triggered by `uv sync`) no longer wipes the hash registry down to a single package's entries. The scanner also tolerates source-less modules (e.g. an empty `__init__.py`) instead of raising `OSError` on Python < 3.13. ([#6614](https://github.com/reflex-dev/reflex/issues/6614))
- Fixed `State.router.url` reflecting a stale query string after the URL was changed with `window.history.replaceState`/`pushState` (e.g. from `rx.call_script`). React Router's location does not observe direct history manipulation, so the query and hash are now read from the live `window.location` when building `router_data`, and the next event sent to the backend reports the correct URL (the path stays basename-relative so `frontend_path` is not applied twice; embedded apps keep using the in-widget memory router). A direct history mutation is intentionally not a navigation and does not itself emit an event — use `rx.redirect(..., replace=True)` when you need the URL change to update the router reactively and trigger `on_load`. ([#6625](https://github.com/reflex-dev/reflex/issues/6625))
- pyi_generator no longer includes underscore-prefixed props in generated .pyi files. ([#6628](https://github.com/reflex-dev/reflex/issues/6628))
- Frontend-only events (e.g. `rx.toast`, `rx.redirect`) returned from a middleware's `preprocess` are now emitted to the client instead of being enqueued on the backend event queue, where they had no registered handler and raised `KeyError`. The frontend/backend split that already applied to handler-yielded events is now shared via a `_route_events` helper and applied to middleware-preprocess updates too. ([#6644](https://github.com/reflex-dev/reflex/issues/6644))

### Performance

- Speed up component creation by resolving field defaults lazily (via class-level descriptors) instead of eagerly on every instance, caching each component class's event triggers, and memoizing `to_camel_case`. ([#6576](https://github.com/reflex-dev/reflex/issues/6576))


## v0.9.4 (2026-06-03)

### Deprecations

- Component-returning `@rx.memo` again accepts `key` without an `rx.RestProp` (with a deprecation warning), so `rx.foreach` call sites that set the react `key` keep working; this fallback is removed in 1.0. Other base props (`id`, `class_name`, `style`, `custom_attrs`, `ref`) and identity fields like `tag`/`library` still raise — declare an `rx.RestProp` to forward them.

### Features

- Dependency tracking now follows through hybrid properties, so computed vars that read a `hybrid_property` correctly recompute when the underlying state vars change. ([#3806](https://github.com/reflex-dev/reflex/issues/3806))
- The component memo implementation now lives in `reflex_base.components.memo` and is exported as `rx.memo`. Added `EMPTY_VAR_STR` and `EMPTY_VAR_INT` sentinel vars as memo-friendly defaults. ([#6517](https://github.com/reflex-dev/reflex/issues/6517))

### Bug Fixes

- Pin `es-toolkit@1.46.1` via package overrides to work around upstream breakage in recharts and es-toolkit. ([#6570](https://github.com/reflex-dev/reflex/issues/6570))
- Unpin `es-toolkit@1.46.1` via package overrides and bump vite to 8.0.14 to work around upstream breakage in recharts and es-toolkit. ([#6571](https://github.com/reflex-dev/reflex/issues/6571))

### Miscellaneous

- Removed the `Templates.CHOOSE_TEMPLATES` and `Templates.REFLEX_TEMPLATES_URL` constants, which supported the now-removed open-source templates `reflex init` option. ([#6592](https://github.com/reflex-dev/reflex/issues/6592))
