Skip to content

Releases: reflex-dev/reflex

v0.3.5

06 Dec 16:00
94f657c
Compare
Choose a tag to compare

Known Issues

Using rx.el.* namespace tags with State vars is not currently working (#2264)

Breaking Changes

  • Component._get_app_wrap_components is now a staticmethod for performance reasons.

Deprecations

Deprecated features will not be removed until reflex-0.4.0.

Improvements

Performance

This release includes numerous performance improvements during both compile phase and at runtime.

Backend

  • [REF-1035] Track ComputedVar dependency per class by @masenf in #2067
    • Reduce memory and deserialization time for every app user.
  • [REF-201] Separate on_load handler from initial hydration by @masenf in #1847
    • Avoid expensive hydration of entire state when navigating between pages (with @ElijahAhianyo)

Frontend

Each substate in an app can now be accessed independently. Components which depend on any state are automatically pulled out of the main page component and defined within separate "memoized" components that only update when the substates they directly depend upon have changed.

This improves re-render time on some reflex-web pages by 20x πŸš€

  • [REF-889] useContext per substate by @masenf in #2149
  • [REF-144] Add context in each component to prevent rerenders by @masenf in #2198
  • Memoize markdown component_map by @masenf in #2219
  • Support hooks in custom components (state, addEvents) by @masenf in #2234
  • [reflex-web tweaks] Do not memoize children of InputGroup by @masenf in #2230
  • [REF-1349] RechartsCharts and ResponsiveContainer must be memo leaf by @masenf in #2240
  • Generalize MemoizationLeaf Component mixin (and apply to Cond and NextHead) by @masenf in #2247
  • [REF-1352] Markdown component_map hash improvements by @masenf in #2241

Compiler

  • _valid_children and _invalid_children accessible from class by @Lendemor in #2192
    • [fixup] _valid_children and _invalid_children pyi_generator and graphing components by @masenf in #2194
  • Speed up reflex CLI imports by @picklelo in #2185
  • Use singleton app provider to speed up compiles by @picklelo in #2172

Allow Multiple Subclasses of rx.State

Any module can now create substates without importing from a base state defined in the App.

Third-party components may define and use their own substates.

(Note: Working event handlers for substates defined within nested functions are still TODO.)

Improved Basic HTML Elements

The rx.el namespace provides access to basic HTML tags, such as a, div, and p, which can be used to build the frontend instead of using Chakra components. This can be useful when styling the app via tailwind.

As Reflex moves to using radix-ui components, this cleans up the API because many radix components directly inherit from basic HTML elements.

  • HTML Refactor by @Alek99 in #2164
  • [REF-1158] Move chakra-only deps to chakra lib by @masenf in #2171
    • If no chakra components are used, then chakra deps are not installed for the app.
    • [fixup] [reflex-web tweaks] chakra Icon is a ChakraComponent (use sx for style) by @masenf in #2231

Allow PIL images to be serialized in alternate formats

Setting the image.format attribute on a PIL Image.Image object controls what format the image is serialized as when sending to the frontend via data URI.

Add/Subtract time delta with rx.moment

Dependency Bumps

Other Improvements

Bugfixes

Fix _hover, _focus and other leading underscore props

Others

  • fix name for import var when is default and add tests by @Lendemor in #2214
  • code_block responds to color mode by default by @masenf in #2228

Data Editor

Internal

New Contributors

Full Changelog: v0.3.4...v0.3.5

v0.3.4

17 Nov 21:11
0870658
Compare
Choose a tag to compare

This release re-exposes top level names under the reflex namespace that were erroneously removed in v0.3.3

New Features

  • [REF-723+] Upload with progress and cancellation by @masenf in #1899

What's Changed

Full Changelog: v0.3.3...v0.3.4

v0.3.3 [yanked]

15 Nov 19:29
9d13e2d
Compare
Choose a tag to compare

New Features

Python 3.12 is now supported

by @masenf in #2006

Next.js upgrade from 13 to 14

by @Lendemor in #2142

Clear Form using reset_on_submit prop

You can use the reset_on_submit on a form to reset form values to their original states after submitting the form. Simply set the value to True.

rx.form(
    rx.input(id="text", placeholder="text"),
    rx.button("Submit", type_="submit"),
    reset_on_submit=True,
)

(by @masenf in #2012)

Forms support dynamic names.

  • Dynamic refs / ids don't really work but you can use dynamicΒ names instead

    rx.form(
        rx.vstack(
            rx.input(name="name_input"),
            rx.hstack(rx.pin_input(length=4, name="pin_input")),
            rx.number_input(name="number_input"),
            rx.checkbox(name="bool_input"),
            rx.switch(name="bool_input2"),
            rx.slider(name="slider_input"),
            rx.range_slider(name="range_input"),
            rx.radio_group(["option1", "option2"], name="radio_input"),
            rx.select(["option1", "option2"], name="select_input"),
            rx.text_area(name="text_area_input"),
            rx.input(
                name="debounce_input",
                debounce_timeout=0,
                on_change=rx.console_log,
            ),
            rx.button("Submit", type_="submit"),
        ),
    ),
  • Use rx.Var.range (similar to python’s range ) with rx.foreach to dynamically create form elements with dynamic names. rx.Var.range(v1, v2, step) takes in start, end and step values which should be integers or Var integers.

    class State:
        grid: int = 4
    
        def handle_submit(self, form_data: dict):
            print(form_data)
    
    rx.form(
        rx.responsive_grid(
            rx.foreach(
                rx.Var.range(State.grid),
                lambda i: rx.foreach(
                    rx.Var.range(State.grid),
                    lambda j: rx.input(
                        name=f"grid_{i}_{j}",
                        placeholder=f"grid {i} {j}",
                        key=f"{i}_{j}",
                        width="4em",
                    ),
                ),
            ),
            columns=[State.grid],
        ),
        rx.button("Submit", type_="submit"),
        reset_on_submit=True,
        on_submit=State.handle_submit,
    ),

New form-based code should prefer to use the name attribute to avoid the overhead of using refs for no specific gain (unless focus or value setting is required).

(by @masenf in #2012)

Improvements

  • Assume secure protocol (wss://) and no port If the frontend is being accessed via HTTPS and the API_URL is either localhost, 0.0.0.0 or :: and uses a non-secure protocol by @masenf in #2129
  • Reduce Syntax highlighter footprint by @ElijahAhianyo in #2037
  • Lazy import modules in reflex by @picklelo in #2144

Doc fixups

Bug Fixes

  • fix an issue where some fields in State.router.headers were not getting updated by @Lendemor in #2133
  • Resolve peer dependency conflict causing package-lock.json to relock on every run by @ElijahAhianyo in #2106

Other Changes

New Contributors

Full Changelog: v0.3.2...0.3.3

v0.3.2

04 Nov 00:13
f990530
Compare
Choose a tag to compare

Thank you to our wonderful users and contributors! πŸ‘ πŸŽ‰

New Features

Expose stop_propagation and prevent_default on Event Handlers

When an event trigger should not propagate to DOM elements nested below it use .stop_propagation.

When an event action should override the browser default (like following a link), use .prevent_default.

Each of these "event actions" will trigger the frontend to call the corresponding method on the DOM event associated with the event trigger. Both actions may be applied to the same event handler.

  • Expose DOM event actions on EventHandler, EventSpec, and EventChain (stopPropagation) by @masenf in #1891
  • Do not stop prop is there is no prop to stop by @masenf in #2116

Gunicorn Worker Class

The gunicorn_worker_class may be specified in rxconfig.py to configure low-level uvicorn settings when running in prod mode. See example in dicussion #2070.

  • Expose gunicorn_worker_class via Config by @masenf in #2084

Components can be passed as props

Components can now accept props with type Var[Component], which allows for greater customization of components and greater flexibility when wrapping third-party components.

This only works for static components passed at compile-time. Components cannot be used in a State Var.

Github Codespaces

Creating a codespace from the reflex repo is now supported. Be sure to open the Backend URL in the browser first (or mark the port as Public) to allow the frontend to access the backend via websocket.

Improvements

Add orientation prop to rx.stepper

  • Add 'orientation' Property to Reflex Stepper Components by @shu-qian in #2089

Add column resize for data editor

Doc fixups

Template Improvements

Hosting Service CLI

  • [REF-1042] Hosting CLI: check the user selected app name by @martinxu9 in #2102
  • Hosting CLI: use http endpoint to return deploy milestones by @martinxu9 in #2085

Other Improvements

Bug Fixes

README Translations

New Contributors

Full Changelog: v0.3.1...v0.3.2

v0.3.1

28 Oct 00:57
2693340
Compare
Choose a tag to compare

A quick followup release from v0.3.0

What's Changed

v0.3.0

27 Oct 21:43
5e444a7
Compare
Choose a tag to compare

Breaking Changes

Drop Python 3.7 Support

Victory charts are completely removed in this release.

Graph and chart functionailty has been replaced by Recharts, see the docs for more examples.

Removal of Deprecated Browser Storage API

rx.Var Fields are Renamed

Most users are not interacting the Var class directly, but if you are, the following fields have been renamed:

  • name -> _var_name
  • type_ -> _var_type
  • state -> _var_state
  • is_local -> _var_is_local
  • is_string -> _var_is_string

This allows rx.Base and rx.Model classes using these field names to be accessed through State vars.

Prop Values are Validated

Each component prop now defines values as typing.Literal, which has two effects:

  • In IDEs, the allowed values for a field will be prominently displayed.
  • When compiling, invalid literal values for props will raise an exception.

The following code will now raise ValueError

rx.button("Foo", color_scheme="silly")
ValueError: prop value for color_scheme of the `Button` component should be one of the following: none,gray,red,orange,yellow,green,teal,blue,cyan,purple,pink,whiteAlpha,blackAlpha,linkedin,facebook,messenger,whatsapp,twitter,telegram. Got 'silly' instead

If you need to pass an unrecognized prop value, you can wrap it in an rx.Var.

rx.button("Foo", color_scheme=rx.Var.create("silly"))

New Features

New Base Template

When running reflex init in a new directory, a multi-page template will be deployed instead of the Welcome to Reflex page. This provides a better starting point for more complex apps.

Use reflex init --template blank to generate a new app with the previous template.

New Component: rx.data_editor

Based on the Glide Data Grid, the new rx.data_editor component supports in place editing of data tables and is more feature rich than the existing rx.data_table component.

See the docs for more examples and details.

(Note: pandas dataframe is not currently supported, but will be coming soon)

State.router

The State.router property provides access to the current page's router data in a way that can be accessed from both the frontend and the backend.

Previous State.get_current_page(), State.get_query_params(), and others are now deprecated.

  • deprecate get_ methods for router_data, use BaseVars instead by @Lendemor in #1967

New component: rx.moment

Simple date/time formatting on the frontend, and provides an event trigger that can be fired peridically from the frontend.

Reflex Hosting Preview

This release includes support for the new Reflex Hosting service, currently in closed testing, please reach out on Discord for more information.

Demo App

Running reflex demo will now open a demo app based on the new base template showing some reflex features.

(Currently using a remotely hosted version of the app, but subsequent release will run the demo app locally.)

Radix Themes Preview

Reflex is moving away from Chakra-UI component to Radix-UI. And some of the new components are available in this release for testing in the reflex.components.radix.themes module. More details to follow.

  • [REF-668] Wrap MyApp with radix Theme component by @masenf in #1867
  • [REF-938] Fix up radix themes issues by @masenf in #2002

Improvements

Automatic API_URL

Most users will not have to explicitly set API_URL unless their frontend and backend are running on different hosts or via a load balancer.

When the default API_URL of http://localhost:{backend_port} is used, and the frontend is not being accessed on localhost, assume that the backend and frontend are on the same host.

  • [REF-843] Automatically update api_url and deploy_url by @masenf in #1954

Support for Static Sites

Do not display the connection error banner or attempt to connect to the backend if the app does not use State.

Improve reflex export

  • Support exporting to zip archives to a dir that is not cwd (to be use by hosting cli) by @jackie-pc in #2005
  • [reflex export] backend.zip excludes dirs that look like venv dirs by @jackie-pc in #2009

Access Relationship Attributes on rx.Model

  • Improve Var type handling for better rx.Model attribute access by @masenf in #2010

Autogenerate missing requirements.txt

An app must have a requirements.txt to be deployed via the hosting service, so Reflex will create one based on top-level packages in the environment where it is running.

  • Autogenerating Dependencies During Deployment by @Alek99 in #2033

Support callback in rx.call_script

When running arbitrary script, it is now possible to pass the result back to an Event Handler. See the updated docs for more examples.

Miscellaneous

Bug Fixes

  • Fix custom components special props by @picklelo in #1956
  • Fix charts not displaying without specifying width and height
    • ChartBase.create: include default min dimensions (RESUB) by @masenf in #1975
  • Fix Cookie and LocalStorage values being reset on navigation
  • Bug: changing type of playing by @Billa05 in #1986
  • Rehydrate client storage after rx.remove_local_storage and rx.remove_cookies by @ElijahAhianyo in #1998
  • multi_select somewhat usable by @masenf in #1861
  • fix fnm version check by @Lendemor in #2014
  • Resolve npm path and fnm path on Windows by @masenf in #2015
  • Radix Themes style notation fix by @ElijahAhianyo in #2025
  • Generate state delta from processed state instance by @masenf in ...
Read more

v0.2.9

09 Oct 22:43
86c624e
Compare
Choose a tag to compare

Breaking Changes

rx.constants module refactored

  • Many names have changed for better organization and namespacing of the growing number of constant values.
    • rx.constants is not really a public API, but some existing code may have been accessing values in this module.
  • code cleanup (split constants into a folder) by @Lendemor in #1866

New Features

Core Graphing Library is now Recharts

The API for rendering charts and graphs has changed.

  • See the docs for examples and more information.
  • Victory charts are deprecated and will be removed in a subsequent release.
    • rx.data is no longer used.
  • #1878

Run Arbitrary Javascript from Event Handler

  • rx.call_script: a real EventHandler to execute arbitrary javascript by @masenf in #1860

Redirect into New Window

  • return rx.redirect("https://google.com", external=True) to open page in new tab/window
  • allow external link for redirect by @Lendemor in #1902

HTML Editor Component

Improvements

  • Allow arbitrary Reflex components to map to markdown tags for more customizable styling.
  • Include scripts in <head> for every page by setting head_components prop in rx.App
  • Adding Missing Props to button, button_group, and circular_progress
  • Add Readme.md for turkish language by @09u2h4n in #1922
  • Pin frontend package versions by @picklelo in #1920
    • More reliable deploys without bringing in unexpected upstream changes

Bug Fixes

  • component: imports override _get_dependencies_imports by @masenf in #1859
  • Fix regression where rx.table stopped working with state Var
  • MutableProxy fixes when accessing list, dict, or set vars on a State
    • MutableProxy wraps values yielded by __iter__ by @masenf in #1876
    • State.reset uses deepcopy on defaults by @masenf in #1889
    • state: get_value unwraps MutableProxy first by @masenf in #1887
    • state: subclass of MutableState must return _mark_dirty return value by @masenf in #1898
  • fix rx.image src not working with state by @Lendemor in #1915
  • fix menu items= API by @Lendemor in #1905

Other Changes

New Contributors

Full Changelog: v0.2.8...v0.3.0

v0.2.8

22 Sep 17:57
83d7a04
Compare
Choose a tag to compare

✨ This release is made possible in part by users like YOU! ✨

Breaking Changes

CopyToClipboard component has been removed.

Use the rx.set_clipboard special event instead.

New Features

get_event_triggers API

The new Component.get_event_triggers API combines the old get_triggers and get_controlled_triggers methods into a unified API (the previous methods will continue to work in 0.2.8, but wrapped components should move to the new API).

The new API is more flexible, providing control over handler and trigger argument mapping. The method is expected to return a dictionary of callables. The keys are the names of the triggers in the react component. The values are callables whose signature defines the javascript trigger signature and the return value is a list of args that will be passed to the python EventHandler function.

This allows wrapping of components that accept non-standard event handler functions. Typically a lambda is used to map arguments, but a regular function with type annotations can also be used to enable extended Var operations like indexing.

For example, the FormSelect component uses a non-standard signature for on_change, this can now be accomodated in the new API.

class FormSelect(rx.Component):
    library = "@patternfly/react-core"
    tag = "FormSelect"

    def get_event_triggers(self) -> Dict[str, Any]:
        return {
            EventTriggers.ON_CHANGE: lambda _e, value: [value],
        }

rx.download special event

The new download event prompts the frontend browser for file download.

It can be used directly as an event trigger:

rx.button("Download file", on_click=rx.download("/uri/for/file.extension", "target_file.extension")

Or it can be yielded from a backend event handler:

def export_data(self):
    ...
    # do export logic here and write to filepath
    # then
    yield rx.download(filepath, filename)

Register Serializers for Custom Types

A one-arg callable in a Reflex app or component module with @rx.serializer decorator will be considered a serializer for the type of its argument. This allows arbitrary types used on the backend to be accessed on the frontend, as long as there is a serializer defined that returns a JSON serializable value.

For example, the following code is used to serialize plotly Figure objects.

import json
from plotly.graph_objects import Figure
from plotly.io import to_json

@rx.serializer
def serialize_figure(figure: Figure) -> list:
    return json.loads(str(to_json(figure)))["data"]

Background Task Event Handlers that do not block other Events

An async EventHandler function in a State that is decorated with @rx.background is considered a "Background Task". When triggered by the frontend or chained from another event handler, it will spawn a long running task that will NOT block other EventHandlers from running.

There are three main differences from a normal EventHandler to be aware of:

  • Background Task must be async
  • Background Task cannot directly modify state values and state values may be stale if other events have modified the state since the task started running.
    • Only read or write state vars inside an async with self context block, where exclusive access to the latest state is guaranteed.
  • Background Task cannot be directly called from another event handler.
    • Must yield or return the background task to chain it from another handler.
class State(rx.State):

    counter: int = 0

    @rx.background
    async def bg_task(self):
        for ix in range(10):
            async with self:
                # state mutation is only allowed inside context block
                self.counter += 1

            # await long operations outside the context to avoid blocking
            await asyncio.sleep(0.5)

Full documentation for this feature is still being developed. Please post comments regarding background tasks on the discussion thread.

  • rx.background and StateManager.modify_state provides safe exclusive access to state by @masenf in #1676

Improvements

Support Reactivity for rx.Base fields

Modifying fields on an rx.Base instance will trigger updates in the state without having to reassign them. This also applies when working with fields that are container types such as list and dict.

  • Reassign state Var when fields on a Base instance change by @masenf in #1748

Better Error Messages

Usability

Bug Fixes

  • added check to remove local import starting from . by @wassafshahzad in #1807
  • exec: print the URL, not the address the server binds to by @masenf in #1846

Minor Changes and Fixups

New Contributors

Full Changelog: v0.2.7...v0.2.8

v0.2.7

07 Sep 23:16
47d789e
Compare
Choose a tag to compare

πŸ™Β Thanks to our supportive community and helpful contributors! πŸ’ͺ

Breaking Changes

Default Websocket Endpoint is now /_event #1542

Upload endpoint also moved to /_upload.

Any reverse proxy configurations that were explicitly forwarding /event and /upload to the backend server should be updated to use the new endpoints.

App kwarg connect_error_component is removed.

Use overlay_component instead. (#1379)

New Features

Client-side Storage integrated with State #1629

  • Allow rx.LocalStorage and rx.Cookie type vars in a State class that are automatically persisted in the client browser when modified on the backend.
  • These values can be used in frontend or backend code just like any other state Var.
class State(rx.State):
	my_token: rx.LocalStorage = ""
  my_hour_cookie: rx.Cookie = rx.Cookie("initial", max_age=3600)

  def set_token(self):
    self.my_token = str(uuid.uuid4())

  def update_cookie(self):
    if self.my_hour_cookie == "initial":
      self.my_hour_cookie = "updated"

Implement on_mount and on_unmount for all components #1636

These new event handlers, present on all components, tie into React’s useEffect hook and are used to trigger backend events needed to initialize a component when it loaded in a page.

Note: on_mount will fire twice in dev mode due to the use of React’s StrictMode.

Note: on_mount will not fire for page navigation events between different params of the same dynamic route, since the page itself does not get reloaded so no remount occurs. For navigation events, see on_load argument of app.add_page.

FNM is now used to install nodejs on POSIX platforms

by @ElijahAhianyo in #1606 #1701

frontend_packages are automatically determined #1607

  • frontend_packages are inferred based on the library prop of a wrapped component, instead of having to specify them manually in the rxconfig.py file.
  • The library prop may now include a version pin, like **library =** "gridjs-react@^6.0.1"
  • The package.json list of frontend dependencies only includes components that are actually used in the app, which decreases bundle size.
  • To include additional dependencies used by a component, specify them in the new lib_dependencies prop of the wrapped component.

Per-component prop autocompletion for IDEs #1708

Generated .pyi files provide better function signatures for component create methods, enumerating most recognized props.

Further enhancements will be supplied in a future release to include per-prop documentation and improved signatures for event handlers.

Support Breakpoints in VSCode and PyCharm #1653

  • Breakpoints set in the IDE will be respected when running the project in dev mode. See DEBUGGING.md for an example.

Expose basePath configuration option #1724

Support running multiple reflex apps from the same domain by changing the basePath prefix that the frontend uses (by @nevdelap).

Improvements

  • Validate component children by @ElijahAhianyo in #1647
  • Refactor zipping in reflex export by @martinxu9 in #1668
  • Avoid leaking secrets in log files and on the console.
    • fix:issue-1667;added if condition check to not echo DB_URL by @shashank40 in #1681
  • Automatically display a Modal when the backend is unable to connect.
    • ConnectionModal and ConnectionBanner cleanup by @masenf in #1379
  • Add contains, reverse operations for Var by @martinxu9 in #1679
  • Add special var for upload: clear_selected_files by @martinxu9 in #1703
  • Support automatic serialization of date, datetime, time, and timedelta Vars in a State class.
  • Raise TypeError when attempting to incorrectly use a state Var in a bool or iter context.
    • Var: __**bool__** and __**iter__** always raise a TypeError by @masenf in #1750
  • Allow dynamic routes to work with static hosting (github pages, netlify, s3, etc)
    • Client-side Routing (404 redirect) by @masenf in #1695
    • Fix browser error when navigating to missing route and custom 404 page is not used.
    • No need to run the frontend nodejs process, see updated docker-example.

Bug Fixes

  • ReflexList: reassign field on insert by @masenf in #1652
  • Allow event handlers in parent state to be directly called from child state.
    • state: _init_event_handlers recursively by @masenf in #1640
  • Allow rx.form to work with debounce inputs
    • [REF-526] debounce_input should respect child ref by @masenf in #1717
  • Track var dependencies in comprehensions and nested functions by @masenf in #1728
  • Proper serialization for chained Event payloads by @masenf in #1725

Minor Changes and Fixups

New Contributors

Full Changelog: v0.2.6...v0.2.7

v0.2.6

23 Aug 22:40
57855f5
Compare
Choose a tag to compare

A quick follow-up release to fix issues discovered and reported by our thriving community on Discord. πŸ’ͺ

Fix Regressions

Ensure non-sqlite databases can be used #1661

  • model: only pass "check_same_thread" arg for sqlite database by @masenf in #1662

Block problematic upstream package python-engineio-4.6.0 #1658

  • pyproject.toml: requires python-engineio!=4.6.0 by @masenf in #1663

Other Changes

New Contributors

Full Changelog: v0.2.5...v0.2.6