Releases: reflex-dev/reflex
v0.7.14
Release Notes
[WARNING: different UI output] add style recursive for memo
Previously, we were not adding the app styles to memoized components. Now that's fixed, but in certain apps some of your memoized components might look different, so adjust your styles after upgrading.
- add style recursive for memo by @adhami3310 in #5380
Context on what page failed to evaluate
If you're on Python 3.11+, you will get a helpful message indicating which route is the one that caused the error.
- add context on route during evaluation by @adhami3310 in #5342
Full Logging support
If you want to run reflex with a high loglevel but want to store debug logs just in case. You can set the environment variable REFLEX_ENABLE_FULL_LOGGING to true. This will by default store it in the user directory (something like .locals/shared/reflex). You can change the path of the log file with the environment variable REFLEX_LOG_FILE.
- print debug logs in the user directory under logs by @adhami3310 in #5388
- do not log to file if progress by @adhami3310 in #5402
Components Improvements
- support str for size prop in el.select by @carlosabadia in #5359
- add g svg element by @carlosabadia in #5360
- support float and str for stroke_width prop in recharts components by @carlosabadia in #5358
- adjust rechart types by @Lendemor in #5336
- add str support for some html components props by @carlosabadia in #5378
Bugfixes
- do not run nextjs check on import by @adhami3310 in #5352
- Handle REFLEX_ENV_FILE at init time by @masenf in #5349
- do not prematurely import app module if providing app_module_import by @adhami3310 in #5350
- detect class var that are forward ref by @Lendemor in #5362
- fix reload paths being restricted to the app dir by @adhami3310 in #5363
- make get_props use get_js_fields by @adhami3310 in #5361
- fix checking for migrations in granian by @adhami3310 in #5348
- fix app_wraps not being passed from inside a rx.memo by @Lendemor in #5387
- no need to kill nextjs on package change by @adhami3310 in #5389
- ignore visited components for all_app_wrap_components by @adhami3310 in #5404
- compile custom components before we get app wraps of the pages by @adhami3310 in #5405
Chores
- update deps 0714 by @adhami3310 in #5328
- delete wsl integration test by @adhami3310 in #5368
- update pyi hashes by @adhami3310 in #5365
- enable all ruff rules but not really by @adhami3310 in #5367
- add uv sync to setup build env by @adhami3310 in #5366
- upgrade deps just before 0714 by @adhami3310 in #5373
- fix infinite loop in pyi generator by @adhami3310 in #5354
- Enable wide assortion of ruff rules by @adhami3310 in #5372
- move environment into its own file by @adhami3310 in #5403
Misc
- add repr to plugins by @adhami3310 in #5364
- some prepwork to anticipate for removing pydantic from propsbase by @Lendemor in #5370
- ignore log for hot reload by @adhami3310 in #5369
- identify app_class in telemetry events by @Lendemor in #5374
- track node and bun version by @adhami3310 in #5375
- Revert "identify app_class in telemetry events (#5374)" by @adhami3310 in #5383
- another way to check on enterprise usage by @Lendemor in #5400
Full Changelog: v0.7.13...release/reflex-0.7.14
v0.7.13
Release Notes
Remove Pydantic as a base class of Component
rx.Component
used to inherit from BaseModel
, but that's no longer the case. We opted to write our own Metaclass to handle the specific needs of Components better.
This has great improvements for hot reload time for small apps as Pydantic spent around 75% of import time just deep copying fields. On my own machine, a hot reload of a simple app went down from ~1.2sec to just around 200ms!
While this is not intended to be a breaking change, it's likely that a very introspective code could behave differently with this one. So please test it and report to us so we can preserve behavior as best as possible.
- remove pydantic as base class of component by @adhami3310 in #5289
length() for dicts
If you are using object vars (State fields of type dict or Base/dataclasses), you can now call .length()
on them. This is a simple wrapper over .keys().length()
.
- add length var operation for objects by @adhami3310 in #5318
Allow Vars to be the result of the render function of Foreach
This relaxes the requirement from being a component. Vars are wrapped in a Fragment.
- allow rendering vars in foreach by @adhami3310 in #5271
Prefix Config Vars with REFLEX_
The environment variables defined in Config
will now be read with REFLEX_
as a prefix. Previous not prefixed names are still names but are deprecated.
Stronger type checking against partially filled variables
If you were unlucky enough, you might have written some code where you capture some arguments but reflex decides that it wants to give your event handler even more arguments. In these cases, we weren't checking the types of such arguments against the event callback. This now triggers a compilation error.
- add type checking for partially filled events by @adhami3310 in #5288
Ignore certain file formats from hot reload
Granian was reloading on more file formats than necessary, so we manually exclude a set of file formats that are unlikely to be a cause of hot reload. If you still notice weird hot reloads on file changes that are irrelevant to your application, we can append that list with more values.
- ignore certain file formats from granian hot reload by @adhami3310 in #5326
Tailwind V3 is now contained in a module (and rudimentary Reflex Plugin System)
We now have a basic plugins system with a few hooks. It's not very documented, but you can basically provide a list of plugins to the plugins argument in rx.Config
. You can add compile time hooks to create files, modify files, define stylesheets, define javascript dependencies, and more.
We moved our tailwind v3 code to use such plugin system. You should either set tailwind=None
inside of your rx.Config
or set plugins
to [rx.plugins.TailwindV3Plugin()]
. Automatic assumption of tailwind is deprecated.
We're also starting our work on Tailwind V4. You can try it by setting plugnis to rx.plugins.TailwindV4Plugin()
.
- move tailwind to its own module by @adhami3310 in #5169
- make sure the progress count is correct with plugins by @adhami3310 in #5327
- add config to tailwind v4 plugin by @adhami3310 in #5331
Bugfixes
- do not add auto setters on reflex states by @adhami3310 in #5314
- do not broadcast event to all clients if modify state is misused by @adhami3310 in #5322
- send empty files list by @adhami3310 in #5323
- do not delete the .web dir when init-ing by @adhami3310 in #5319
- fix typeddict as annotation by @Lendemor in #5324
Chores
- bump deps 0713 by @adhami3310 in #5309
- crack down on sets for uniqueness by @adhami3310 in #5316
- Use patch to precommit by @adhami3310 in #5279
- update radix deps to 0713 by @adhami3310 in #5335
Full Changelog: v0.7.12...v0.7.13
v0.7.12
Release Notes
Bugfixes
- [ENG-5784] Restrict
update_vars_internal
to browser storage vars by @masenf in #5293 - don't treat name with - differently by @adhami3310 in #5291
- Include required
jsx
andFragment
imports in ComponentVar by @masenf in #5294 - add responsive to vstack and hstack by @adhami3310 in #5298
- load mounts from environment variable for httpx by @adhami3310 in #5297
Chores
- bump to 0.7.12dev by @adhami3310 in #5287
- fix reflex-web ci not having requirements.txt by @adhami3310 in #5296
Full Changelog: v0.7.11...v0.7.12
v0.7.11
Release Notes
[DEPRECATION] rx.next.video
It wasn't particularly usable to begin with.
- deprecate next video by @adhami3310 in #5260
Slightly stronger hydration mismatch strictness
This will stop you from putting rx.el.p
inside of a rx.el.p
and such.
- add invalid children to html components by @adhami3310 in #5261
Add option to disable auto-setters
This can allow you to be more explicit on what public State fields can be set by the user.
- feat: allow disabling auto-setters via state_auto_setters config by @benedikt-bartscher in #4480
Use Javascript syntax over JSX
This shouldn't affect you, but our output code is now using normal Javascript and no JSX syntax. This solves some of the issues we had with context swapping between Vars and Components.
- don't use jsx syntax by @adhami3310 in #5127
Upgrade rx.icon
Lucide has updated their list of icons, and now those changes are available in Reflex.
- update lucide to 507.0 by @adhami3310 in #5269
- update to 508 lucide by @adhami3310 in #5275
Remove Cond as a Memoization leaf
This might improve the runtime performance of your frontend!
Optimizations
- β‘οΈ Speed up function
to_camel_case
by 128% by @misrasaurabh1 in #5239 - use knowledge about generic types to improve their getters and checkers by @adhami3310 in #5245
- optimize rx.color to not use validate literal parameters by @adhami3310 in #5244
Bugfixes
- fix tailwind for lucide icons by @adhami3310 in #5267
Misc
- update backend deps by @adhami3310 in #5250
- update bun version to 1.2.12 by @adhami3310 in #5254
- include symlink folder when running export/deploy by @Lendemor in #5256
- upgrade to nextjs 15.3.2 by @adhami3310 in #5268
Chores
- move coveragerc to pyproject by @adhami3310 in #5231
- i broke pre commit once again by @adhami3310 in #5264
- bump to 0.7.11 by @adhami3310 in #5265
- icons need pyi update by @adhami3310 in #5276
New Contributors
- @misrasaurabh1 made their first contribution in #5239
Full Changelog: v0.7.10...v0.7.11
v0.7.10
Release Notes
Decentralized Event Handlers
You can define some events outside of the state they belong to. This requires using the @event
decorator and typing the first (state) argument with the state it belongs to. It gets used by its name as opposed to State.
format.
import reflex as rx
class State(rx.State):
field: int = 23
@rx.event
def update_field(state: State, new_value: int):
state.field = new_value
def index() -> rx.Component:
return rx.vstack(
State.field,
rx.button(
"Update Field",
on_click=update_field(321),
),
)
app = rx.App()
app.add_page(index)
- decentralized event handlers by @adhami3310 in #5227
Escape hatch: change react version
In case react version upgrade broke your packages somehow, you can use the REACT_VERSION
environment flag to change it. We don't support this flag indefinitely though, and it's very much not safe to set.
- add escape hatch for react version by @adhami3310 in #5225
Decimal support in Vars
You can now use decimal in state, but it converts it to a float when sending it to JS. Devin has contributed some of this PR before needing to intervene a bit.
- Add decimal.Decimal support to serializers and NumberVar by @devin-ai-integration in #5226
Style for dragging over upload component
on_drop
for Upload should now support the list syntax. Also adds a style to the default component when a file is being dragged over it.
[Regression Fix] Lifespan tasks
If you were using lifespan tasks along api
or api_transformer
, it might not have been running as expected. It should be fixed now.
This also fixes hot reload on Windows.
Bugfixes
- do not add requirementstxt if pyproject exists by @adhami3310 in #5185
- do not wrap dict in mutable proxy by @adhami3310 in #5193
- validate classname by @adhami3310 in #5204
- get back python-dotenv errors for environment env file by @adhami3310 in #5203
- fix ai template by @adhami3310 in #5202
- slicing a list is not a mutable proxy directly by @adhami3310 in #5221
- [ENG-5696] unwrap Var-typed annotations in @rx.memo signature by @masenf in #5223
- remove height and with from rx video by @adhami3310 in #5210
Chores
- 0710dev by @adhami3310 in #5195
- add python version for development by @adhami3310 in #5186
- use as posix by @adhami3310 in #5192
- bump deps after 079 by @adhami3310 in #5205
- remove frontend arg from needs_reinit by @adhami3310 in #5214
- move proxy classes into proxy.py by @adhami3310 in #5224
- remove simple page from codspeed by @adhami3310 in #5228
- lock uv update by @adhami3310 in #5238
New Contributors
- @devin-ai-integration made their first contribution in #5226
Full Changelog: v0.7.9...v0.7.10
v0.7.9
Release Notes
Improvements to Tailwind Config Wrapping
Thanks to @itsmeadarsh2008, the tailwind config got expanded:
plugins = [
"@tailwindcss/forms", # simple require
{
"name": "@heroui/theme",
"import": {"name": "heroui", "from": "@heroui/theme"},
"call": "heroui"
},
{
"name": "tailwindcss-theme-variants",
"import": {"name": "themeVariants", "from": "tailwindcss-theme-variants"},
"call": "themeVariants",
"args": {
"themes": {
"light": { "selector": ".light-theme" },
"dark": { "selector": ".dark-theme" }
}
}
}
]
- Support for importing functions from tailwind plugins by @itsmeadarsh2008 in #5121
Enable Granian as default
We have had fixes going into Granian that should make the experience as good as it was on Uvicorn/Gunicorn and in some cases better. There are most certainly issues so feel free to report them and we will do our best to mitigate them.
- reattempt at granian as default by @adhami3310 in #5165
Include all rx.memo
components in the build
This saves us from doing another scan to discover them.
This also adds the ability to call memoized components from dynamic components!
class State(rx.State):
name: str = "Bob"
@rx.var
def count(self) -> rx.Component:
return counter(
name=self.name,
)
@rx.memo
def counter(name: str):
return rx.hstack(
rx.button(name),
rx.button(f"Not {name}"),
)
def index():
return rx.vstack(rx.text("Who Are You?"), State.count)
Deprecate .api
in favor of api_transformer
If you were doing something like:
app = rx.App()
@app.api.get("/pong")
def pong():
return {"message": "pong"}
You should instead do
fastapi_app = FastAPI()
@fastapi_app.get("/pong")
def pong():
return {"message": "pong"}
app = rx.App(api_transformer=fastapi_app)
The api_transformer
takes one or multiple (a list) of Starlette/FastAPI apps. It can also take a function that takes ASGIApp
and returns a different ASGIApp
that mounts the previous one. For example, the above code is equivalent to:
from reflex.utils.types import ASGIApp
fastapi_app = FastAPI()
@fastapi_app.get("/pong")
def pong():
return {"message": "pong"}
def fastapi_transformer(app: ASGIApp):
fastapi_app.mount("", app)
return app
app = rx.App(api_transformer=fastapi_transformer)
- starlette over fastapi by @adhami3310 in #5069
- delay api mounting until app finishes compile by @adhami3310 in #5184
Raise error when using @rx.event
with events starting with an underscore.
Private events is not a thing and this can help to error earlier.
- raise error on private events by @adhami3310 in #5152
Replace typer
with click
In our quest to cut down on dependencies we are simplifying our CI across reflex
and reflex-hosting-cli
to use click
over typer
(which what typer
uses under the hood).
- click over typer by @adhami3310 in #5154
- add no interactive back by @adhami3310 in #5191
Misc
- output a slightly more helpful error message when we cannot download β¦ by @adhami3310 in #5140
- treat small tuples different with figure out type by @adhami3310 in #5161
- bump frontend deps and bun by @adhami3310 in #5162
Bugfixes
- handle deocrated pages better by @adhami3310 in #5159
- exit gracefully when set_focus is passed a nonexistent argument by @adhami3310 in #5149
- error when var is given something not a str by @adhami3310 in #5164
- ignore env var set to empty string by @adhami3310 in #5167
- fix upload on drop by @adhami3310 in #5160
- fix for set_focus not binding
this
by @adhami3310 in #5183 - restore get_decorated_pages behavior and deprecate it by @adhami3310 in #5194
Chores
- properly shutdown socketio and sqlalchemy async engine in AppHarness by @benedikt-bartscher in #5146
- bump to 0.7.9dev by @adhami3310 in #5145
- remove distro by @adhami3310 in #5158
- remove minor version from ci by @adhami3310 in #5163
- uv lock by @adhami3310 in #5176
New Contributors
- @itsmeadarsh2008 made their first contribution in #5121
Full Changelog: v0.7.8...v0.7.9
v0.7.8
Release Notes
is_none()
and is_not_none()
operations.
If you were getting some of those pesky lint errors because you were doing some_var == None
, you can do some_var.is_none()
instead.
- add is none by @adhami3310 in #5136
Call event handlers with keyword arguments
Although pyright will be mad at you.
import reflex as rx
class State(rx.State):
"""The app state."""
field: int = 0
@rx.event
def change_field(self, new_value: int):
"""Change the state field."""
self.field = new_value
def index() -> rx.Component:
return rx.button(
"Click me!",
State.field,
on_click=State.change_field(new_value=2),
)
app = rx.App()
app.add_page(index)
- Allow calling event handlers with keyword arguments by @adhami3310 in #5124
NextJS upgrade (15.3.0)
This includes faster builds if you enable the environment variable REFLEX_USE_TURBOPACK
.
- nextjs 15.3 by @adhami3310 in #5125
Bugfixes
- i hate order of precedence by @adhami3310 in #5134
- Read environment secrets in state at import time [ENG-5426] [ENG-5455] by @adhami3310 in #5120
- make event statically type-able by @adhami3310 in #5135
- add str to callback for call_function by @adhami3310 in #5139
Chores
- bump to 0.7.8dev by @adhami3310 in #5129
- update supported version in security by @adhami3310 in #5128
- enable UP ruff rule by @adhami3310 in #5137
Full Changelog: v0.7.7...v0.7.8
v0.7.7
Release Notes
el.input
with type=range
and type=number
correctly reports events of type (float) -> Any
Sames goes for el.input
with type=checkbox
and event type (bool) -> Any
.
This can be a subtle breaking change if you had code depending on this small detail.
rx.el.input(
type="checkbox"
on_change=rx.console_log # prints false and true now
)
- allow int and float typing for input elements behind a warning by @adhami3310 in #5098
Bun version behavior fixes
Reflex will use system host if either:
- You passed REFLEX_USE_SYSTEM_BUN. It will warn you if your version of
bun
is outdated, but will ultimately let you run reflex. - You don't have a reflex-installed
bun
and you do havebun
installed on your system and it's up to date.
Otherwise, Reflex uses or downloads/installs or updates its local version of bun that is shared between your reflex applications.
- be less whiny about bun version and suggest alternatives by @adhami3310 in #5106
Hosting CLI Improvements
Reflex hosting cli will now support uploading a local sqlite db as long as it is less than 25mb. This will give the hosted site an ephemeral database. Meaning that new data added could be lost but data uploaded is always persisted.
To achieve this a user must leverage the cloud config (reflex cloud config
) with the following flag include_db: True
Bugfixes
- fix imports lib dependencies by @Lendemor in #5109
- escape type info in error messages by @adhami3310 in #5107
Chores
- add instruction to use latest python version by @adhami3310 in #5092
- add permission to all workflows by @adhami3310 in #5086
- bump deps by @adhami3310 in #5110
Full Changelog: v0.7.6...v0.7.7
v0.7.6
Release Notes
Admin dashboard is optional now
Admin dashboard (that is, starlette_admin
), is now not included by default. If you want to retain it, just install the starlette-admin
package.
- remove publish command from reflex custom components by @adhami3310 in #5053
Removing custom components publish command
To lower the number of dependencies and making the framework less opinionated about what tools to use, we're removing the reflex components publish
. Our recommendation is to use reflex components build
followed by twine upload
or uv publish
, or really any package upload utility.
- remove publish command from reflex custom components by @adhami3310 in #5053
- reintroduce python multipart for formdata by @adhami3310 in #5068
- remove twine env vars by @adhami3310 in #5067
Add value
and default_value
to rx.el.select
I don't know why it wasn't there originally.
Add context to add_page
Thanks to @hjpr, now you can provide context
as a parameter for pages to be used by middlewares if you're building Reflex plugins.
- Added param context to add_page for extended functionality for plugins, flows, etc. by @hjpr in #5091
Bugfixes
- Resolve async computed vars in background task by @masenf in #5057
- fix package manager raise on none logic by @benedikt-bartscher in #5056
- [ENG-4921] Avoid infinite loop in _mark_dirty_computed_vars by @masenf in #5058
- retain traceback of foreach untyped var error by @adhami3310 in #5052
- only include devIndicators if it's False by @adhami3310 in #5066
- stream_logs: protect against closed stdout file handle by @masenf in #5071
- improve _isinstance for var types by @adhami3310 in #5072
- use inspect.signature over fullargspec by @adhami3310 in #5076
- change behavior around default style css by @adhami3310 in #5077
- relax remove none logic in cond by @adhami3310 in #5065
- reload config on post_init by @adhami3310 in #5064
- handle literal subclass in issubclass by @adhami3310 in #5081
- Use set_persistent when applying config changes in export by @masenf in #5102
Chores
- fix venv size after uv by @adhami3310 in #5059
- remove pyi files by @adhami3310 in #5074
- really really make sure that we don't make pyi hashes file if we don't need to by @adhami3310 in #5083
- only send reflex error in telemetry by @adhami3310 in #5082
- [ENG-5375] Allow rx.recharts.tooltip for graphing tooltip by @carlosabadia in #5088
Full Changelog: v0.7.5...v0.7.6
v0.7.5
Release Notes
NextJS back at latest version
As we have had more bugs related to the downgrade, we now have upgraded it back and disable turbopack by default. You can overwrite nextjs version with NEXTJS_VERSION
but it is very much NOT SUPPORTED. Expect bugs when you do so.
- expose NEXTJS_VERSION and upgrade nextjs by @adhami3310 in #5039
- warn users about nextjs version by @adhami3310 in #5045
Event handlers as Vars
Not flashy, but you can use handlers in conds and such
on_click=rx.cond(
SnakeState.game_over,
SnakeState.start_game,
SnakeState.pause_game
)
This only works when the event handler takes no arguments, however, you should use the much more reliable:
on_click=rx.cond(
SnakeState.game_over,
SnakeState.start_game(),
SnakeState.pause_game()
)
Where you call the event handlers. You can use lambda syntax to provide arguments for them.
- allow event handlers to be turned into vars by @adhami3310 in #5032
Expose Socket constants for further customizability
Exposes REFLEX_SOCKET_MAX_HTTP_BUFFER_SIZE
, REFLEX_SOCKET_INTERVAL
, REFLEX_SOCKET_TIMEOUT
to be modified.
- expose socket constants by @adhami3310 in #5022
Add support for ndigits for dunder method round for int vars
round(State.int_field, 3)
- add ndigits to round dunder method by @adhami3310 in #5019
Expose run_in_thread
rx.run_in_thread
is a simple wrapper around asyncio to run a function in a different thread.
Allow None
as children of components
Previously we errored, but now we allow it, it doesn't render to anything.
- allow none as a child of components by @adhami3310 in #5043
Allow arguments for rx.memo event handlers
@rx.memo
def counter(on_text: rx.EventHandler[rx.event.passthrough_event_spec(str)]):
return rx.hstack(
rx.button("Increment", on_click=on_text("Increment")),
rx.button("Decrement", on_click=on_text("Decrement")),
)
def index():
return rx.vstack(rx.text("Counter"), counter(on_text=rx.console_log))
You can even define your own event spec
def hello_who(who: rx.Var[str]) -> tuple[rx.Var[str]]:
return (rx.Var.create(f"Hello, {who}!"),)
@rx.memo
def counter(on_text: rx.EventHandler[hello_who]):
return rx.hstack(
rx.button("Masen", on_click=on_text("Masen")),
rx.button("Not Masen", on_click=on_text("Not Masen")),
)
def index():
return rx.vstack(rx.text("Who Are You?"), counter(on_text=rx.console_log))
- allow arguments to be passed to rx memo event handlers by @adhami3310 in #5021
Bugfixes
- load script directory from config [ENG-5131] by @adhami3310 in #5020
- copy styles to the correct dir by @masenf in #5024
- fix wrong domain for gallery backend by @adhami3310 in #5036
- make sure to str the value in console log by @adhami3310 in #5030
- use package path for dynamic icon by @adhami3310 in #5028
- use granian features to improve hot reload by @adhami3310 in #5023
- Khaleel/eng 5281 typeerror unsupported type ellipsis for guess type by @adhami3310 in #5046
- fix cert errors for package install by @adhami3310 in #5050
Chores
- bump to 0.7.5dev by @adhami3310 in #5018
- Improve AppHarness behavior when app already exists in a relative directory by @masenf in #5025
- make test_call_script more reliable by @adhami3310 in #5038
- add integration test for icons by @adhami3310 in #5037
- make pyright happier by @adhami3310 in #5006
- fix iter parent class method by @Lendemor in #5044
Full Changelog: v0.7.4...v0.7.5