Skip to content

Releases: reflex-dev/reflex

v0.8.0

01 Jul 19:37

Choose a tag to compare

Reflex_080.mp4

Release Notes

Breaking Changes

Local JS files

If your app included local .js files (from assets or elsewhere), and those files contain JSX syntax, they must be renamed with a .jsx suffix now.

REMOVED DEPRECATIONS

The following has been removed and was previously deprecated:

  • UploadFile.filename, deprecated in 0.7.1. Use UploadFile.name instead (which strictly returns the file name with no slashes or such). To get the full path, use UploadFile.path.

  • App.error_boundary, deprecated in 0.7.1. Use App.app_wraps (which has other app wraps as well, most likely you would like to provide those, as well as your different error wrap).

  • App.api, deprecated in 0.7.9. Use api_transformer=your_fastapi_app instead. Read: https://reflex.dev/docs/api-routes/overview#api-transformer

  • App.add_custom_404_page, deprecated in 0.6.7. Use add_page with /404 route instead.

  • Component.__init__, deprecated in 0.7.2. Now it only inits the component and doesn't call post init to add events and such.

  • Non prefixed config env vars, deprecated in 0.7.13. Things like ENV_FILE now have to be passed explicitly as `REFLEX_ENV_FILE.

  • Gunicorn configuration env variables, deprecated in 0.7.9. Removed: timeout, gunicorn_worker_class, gunicorn_workers, gunicorn_max_requests, gunicorn_max_requests_jitter. If you would like to customize those, I encourage you to either call gunicorn directly (reflex.App is a factory for ASGI apps), or do so using gunicorn environment variable flags.

  • Inferring TailwindV3, deprecated in 0.7.13. We assume no Tailwind unless explicitly enabled through the plugins config.

  • get_decorated_pages, deprecated in 0.7.9. If you need to use a similar function you most likely need to implement your own page registry.

  • validate_parameter_literals, deprecated in 0.7.11. I don't think anyone but us used this function but it's nonetheless removed now.

  • Var._var_name, Var._var_name_unwrapped, Var.create_safe, and Var._type. All deprecated in various releases. All have better named equivalents.

This was done in this PR:

[MAJOR REWRITE] Replace Next with React Router

NextJS has served us well, but the needs of the framework has grown and we hit certain limits that made NextJS a suboptimal choice. To not go too long, compilation times and other factors have encouraged us to cut down on a big dependency that we barely use most of its features.

Breaking Changes

THIS MOST DEFINITELY HAS BREAKING CHANGES. Especially if you used something deeply attached to how JS works. During this prerelease we are going to triage regressions and fix them til they are at an acceptable state.

  • Static exports are now stored in .web/build/client (instead of .web/_static)

[REMOVED] reflex.suneditor

We have moved suneditor to its own package: https://github.com/reflex-dev/reflex-suneditor

[REMOVED] Experimental layout

We will be leaning more heavily into less in the core package (where less, is less opinionated UI).

  • remove experimental layout and clean up old experiments by @adhami3310 in #5392

[Major Rewrite] rx.State no longer inherits from Pydantic

rx.State is now a simple python Class. Nothing that fancy. The changes were made to be backwards compatible but you can optionally use rx.field(...) (or rx.field(default_factory=...)) to define fields more explicitly.

  • [0.8] remove pydantic as a base class of state by @adhami3310 in #5396
  • fix missing value for mutable state field leading to shared field value by @adhami3310 in #5416

[BREAKING] rx.Component.get_event_triggers is now a classmethod

We still invoke it mostly from a self context, but you should port it to be a classmethod.

  • [0.8] get_event_triggers should be classmethod by @Lendemor in #5344

[Major Rewrite] Remove Pydantic as a dependency of PropsBase

You can use it as before, it's just not a Pydantic class. (TODO: add code here about using component field)

Enable TailwindV4 by default

Newly generated apps with reflex init will have the tailwindV4 plugin enabled by default instead of the v3 one.

Add earlier checks for wrong app names

If you had your name named wrong, now we check that a tad bit earlier in the compile process and with a more helpful message.

Additional Event Info

Now you can use information about the pointer (the mouse thingy) in pointer events. (TODO: remind me to write an example here).

Also you could use on_scroll_end when.. the scroll ends! Unless you are in Safari, in which case you have to wait until they implement that :/

Improved Error Messaging that contains Vars

If you noticed some weird "rx__state__..." names, those are backend vars JS output. Now we strip those form compilation errors and replace them with what you might expect as more normal names. (TODO, add concrete examples)

  • replace compiled state name with module and name in errors by @adhami3310 in #5381

Add suffix to user defined vars to avoid clash with JS keywords

Javascript has a decent amount of keywords, and sometimes you might accidentally call your variable package and get a syntax error. This should solve this.

Built-in style reset

rx.App now has a parameter named reset_style that is True by default. It's there if you are not using Tailwind and you want to reset differences between the browsers.

Hot reload with REFLEX_ENV_FILES

If you are using Granian, now we pass the REFLEX_ENV_FILES environment flag for it to watch its changes.

Bugfixes

Read more

v0.7.14

03 Jun 02:09

Choose a tag to compare

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.

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.

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.

Components Improvements

Bugfixes

Chores

Misc

Full Changelog: v0.7.13...release/reflex-0.7.14

v0.7.13

26 May 19:03

Choose a tag to compare

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.

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().

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.

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.

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.

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().

Bugfixes

Chores

Full Changelog: v0.7.12...v0.7.13

v0.7.12

19 May 21:10
c27bd39

Choose a tag to compare

Release Notes

Bugfixes

Chores

Full Changelog: v0.7.11...v0.7.12

v0.7.11

12 May 21:11
9b8aab9

Choose a tag to compare

Release Notes

[DEPRECATION] rx.next.video

It wasn't particularly usable to begin with.

Slightly stronger hydration mismatch strictness

This will stop you from putting rx.el.p inside of a rx.el.p and such.

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.

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.

Upgrade rx.icon

Lucide has updated their list of icons, and now those changes are available in Reflex.

Remove Cond as a Memoization leaf

This might improve the runtime performance of your frontend!

  • Allow auto memoization of Component Cond by @masenf in #5272

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

Misc

Chores

New Contributors

Full Changelog: v0.7.10...v0.7.11

v0.7.10

05 May 18:48

Choose a tag to compare

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)

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.

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.

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.

  • Upload: drag_active_style and multiple on_drop specs by @masenf in #5207

[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

Chores

New Contributors

Full Changelog: v0.7.9...v0.7.10

v0.7.9

29 Apr 00:26

Choose a tag to compare

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" }
            }
        }
    }
]

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.

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)

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.

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).

Misc

Bugfixes

Chores

New Contributors

Full Changelog: v0.7.8...v0.7.9

v0.7.8

21 Apr 19:10

Choose a tag to compare

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.

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)

NextJS upgrade (15.3.0)

This includes faster builds if you enable the environment variable REFLEX_USE_TURBOPACK.

Bugfixes

Chores

Full Changelog: v0.7.7...v0.7.8

v0.7.7

15 Apr 02:45
f821ce3

Choose a tag to compare

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:

  1. You passed REFLEX_USE_SYSTEM_BUN. It will warn you if your version of bun is outdated, but will ultimately let you run reflex.
  2. You don't have a reflex-installed bun and you do have bun 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

Chores

Full Changelog: v0.7.6...v0.7.7

v0.7.6

08 Apr 23:36

Choose a tag to compare

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.

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.

Add value and default_value to rx.el.select

I don't know why it wasn't there originally.

  • Add value and default_value to rx.el.select by @masenf in #5079

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

Chores

Full Changelog: v0.7.5...v0.7.6