v0.2.8
版本发布时间: 2023-09-23 01:57:49
reflex-dev/reflex最新发布版本:v0.3.3(2023-11-16 03:29:40)
✨ 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],
}
- New API to define triggers by @Lendemor in https://github.com/reflex-dev/reflex/pull/1820
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)
- add download event by @Lendemor in https://github.com/reflex-dev/reflex/pull/1797
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"]
- Add serializers for different var types by @picklelo in https://github.com/reflex-dev/reflex/pull/1816
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.
- Only read or write state vars inside an
- Background Task cannot be directly called from another event handler.
- Must
yield
orreturn
the background task to chain it from another handler.
- Must
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 https://github.com/reflex-dev/reflex/pull/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 https://github.com/reflex-dev/reflex/pull/1748
Better Error Messages
- Style props with Callable Values by @ElijahAhianyo in https://github.com/reflex-dev/reflex/pull/1751
- Type Validation for Var Operations and Enhanced Compatibility by @ElijahAhianyo in https://github.com/reflex-dev/reflex/pull/1674
Usability
- Allow underscores in routes by @ElijahAhianyo in https://github.com/reflex-dev/reflex/pull/1713
- Implemented color_scheme for Tabs Component by @raven-black-dream in https://github.com/reflex-dev/reflex/pull/1792
- Simplify base rxconfig by @picklelo in https://github.com/reflex-dev/reflex/pull/1821
- Number input float by @raven-black-dream in https://github.com/reflex-dev/reflex/pull/1817
- Support custom styling for code in markdown by @picklelo in https://github.com/reflex-dev/reflex/pull/1844
- add option to disable Tailwind by @ElijahAhianyo in https://github.com/reflex-dev/reflex/pull/1842
Bug Fixes
- added check to remove local import starting from . by @wassafshahzad in https://github.com/reflex-dev/reflex/pull/1807
- exec: print the URL, not the address the server binds to by @masenf in https://github.com/reflex-dev/reflex/pull/1846
Minor Changes and Fixups
- use actions/checkout@v4 by @masenf in https://github.com/reflex-dev/reflex/pull/1768
- Bump version to 0.2.7 by @picklelo in https://github.com/reflex-dev/reflex/pull/1782
- check pyi generations are up to date by @jackie-pc in https://github.com/reflex-dev/reflex/pull/1786
- supply default for rx.Model PK for both DB and python to work by @martinxu9 in https://github.com/reflex-dev/reflex/pull/1788
- move dynamic imports to dedicated method by @Lendemor in https://github.com/reflex-dev/reflex/pull/1785
- removed is_read_only from select by @wassafshahzad in https://github.com/reflex-dev/reflex/pull/1799
- numberinput: check
_id is not None
to avoid Var truthiness warning by @masenf in https://github.com/reflex-dev/reflex/pull/1806 - Remove deprecated route decorator by @ElijahAhianyo in https://github.com/reflex-dev/reflex/pull/1815
- Move custom styles to root App file(_app.js) by @ElijahAhianyo in https://github.com/reflex-dev/reflex/pull/1764
- Disable metrics in CI by @picklelo in https://github.com/reflex-dev/reflex/pull/1822
- Remove extra imports from rx.markdown by @picklelo in https://github.com/reflex-dev/reflex/pull/1837
- Prevent Substate class shadowing by @ElijahAhianyo in https://github.com/reflex-dev/reflex/pull/1827
- pyproject.toml: add
packaging
to dep list by @masenf in https://github.com/reflex-dev/reflex/pull/1839 - state: implement copy and deepcopy for MutableProxy by @masenf in https://github.com/reflex-dev/reflex/pull/1845
- allow for non-installable imports by @Lendemor in https://github.com/reflex-dev/reflex/pull/1843
- Format component as React string by @picklelo in https://github.com/reflex-dev/reflex/pull/1848
- use jinja2 to render package.json by @Lendemor in https://github.com/reflex-dev/reflex/pull/1849
- StateProxy rebinds functools.partial and methods that are bound to the proxied State by @masenf in https://github.com/reflex-dev/reflex/pull/1853
New Contributors
- @raven-black-dream made their first contribution in https://github.com/reflex-dev/reflex/pull/1792
Full Changelog: https://github.com/reflex-dev/reflex/compare/v0.2.7...v0.2.8