Breaking Changes
- Reading a plain
@propertyof a Pydantic model or dataclass through a state Var now raisesVarAttributeErrorat compile time. The default serializer does not send such a property, so the Var always rendered empty. Use@pydantic.computed_field, or register anrx.serializerthat includes the value. (#7648)
Features
- Serialize SQLAlchemy
DeclarativeBasemodels without a custom@rx.serializer: loaded columns and relationships are sent, and unloaded or expired attributes are left out instead of raisingDetachedInstanceErrororMissingGreenlet. (#7756) - On a state schema mismatch, a production page now dispatches a cancelable
reflex:state-mismatchevent onwindowbefore it reloads or shows the "new version available" banner. A listener that callsevent.preventDefault()skips both, so the app decides when to reload;event.detailcarries thefrontendandbackendstate schema hashes. (#7653) - With OpenTelemetry tracing enabled, JSON log records (
REFLEX_LOG_JSON=true) emitted inside a span now include itstrace_idandspan_id, so logs can be correlated with traces. (#7668)
Bug Fixes
- Use the browser's current route when building the websocket connection's initial hydration event, so navigation during connection setup cannot run the previous page's
on_loadhandler or redirect. (#7522) - Fix uploads triggered by toast actions or
rx.call_scriptcallbacks failing withReferenceError: filesById is not defined. Such uploads now send the files selected when they run, not when the toast opened. (#7409) - Fix state updates streamed back during an upload being applied more than once, which could restore a value that a newer update had replaced. (#7721)
- Synced
rx.LocalStoragevars in other tabs now reset to their defaults, like a page load, when localStorage is cleared or their key is removed. (#7652) - Fix a
TypeErrorwhen an event handler is called with a proxied state value (such asself.other(self.items)) after one was called with a proxied value of a different kind, such as a dict. (#7673) StringVar.reversed()now reverses Unicode code points, so a character such as an emoji is no longer split into lone surrogates. (#7548)- Type SQLAlchemy
synonym()attributes like the attribute they point to, soState.model.aliascompiles and string operations such as.upper()work on it. (#7756) - Under mypy,
@rx.eventhandlers are typed asEventCallbackinstead ofEventNamespace, so calling one directly no longer fails with"EventNamespace" not callable, and annotations through the event namespace, such asrx.event.EventSpecorrx.event.EventCallback[int], are accepted as types by mypy and pyright. (#7709, #7810) - Calling an event handler with five to eight positional values now type-checks, binding every argument or the leading ones of a longer handler. (#7752)
- An
EventHandlerstored outside a state, e.g. in a dataclass field, now reads back as the handler for type checkers instead ofAny; read through a state instance it is the bound function. (#7755) FunctionStringVar.createaccepts_var_type=EventChain, for a JS function bound to an event trigger as its whole handler. (#7754)- A column of a SQLAlchemy
DeclarativeBasemodel whose column type gives no useful Python type, such asJSON,JSONBorPickleType, now has the type of itsMapped[...]annotation when read through a state var, sodata: Mapped[dict] = mapped_column(JSON)supportsState.model.data["key"], and aMapped[list[str]]JSON column supportsrx.foreachand array operations, without.to(dict). An annotation that refines the column's Python type, such asMapped[dict[str, int]]overdict, is used too; otherwise the column type still decides. (#7798) - Operations on an optional list var (
list[T] | None) holdingNoneno longer crash the page or the production prerender: the list acts as an empty list, socontainsis false,lengthis 0 andjoingives an empty string. As with any empty list,reducewithout aninitialvalue still raises; passinitial=when the list can beNone. (#7800) - A computed var that returns an optional list, tuple, set or frozenset (for example
-> set[str] | None) now reads asArrayVarorSetVarfor type checkers instead ofComputedVar, so its operations type-check. (#7800) - Deprecation warnings now point at the app line that triggered them when the deprecated call runs inside a
reflex_components_*package (for exampleon_change=client_state.set_value), instead of a file insite-packages. (#7811) reflex run --jsonno longer waits on exit for a descendant process that outlives the app and keeps its output open, which could happen on Python 3.13 to 3.15, most often on Windows. (#7855)
Performance
- Inferring the type of a large dict var no longer copies all of its keys and values. (#7057)
- The first event of a handler that takes a
dict, dataclass,TypedDictor Pydantic model argument no longer imports SQLAlchemy on the event loop. (#7802)
Documentation
- The
REFLEX_ENV_MODEentry in the environment variable reference now says thatreflex runandreflex exportset it from--env, and that users should not set it. (#7712)