docs/events/decentralized_event_handlers.md
import reflex as rx
Decentralized event handlers allow you to define event handlers outside of state classes, providing more flexible code organization. This feature was introduced in Reflex v0.7.10 and enables a more modular approach to event handling.
With decentralized event handlers, you can:
To create a decentralized event handler, use the @rx.event decorator on a function that takes a state instance as its first parameter:
import reflex as rx
class MyState(rx.State):
count: int = 0
@rx.event
def increment(state: MyState, amount: int):
state.count += amount
def decentralized_event_example():
return rx.vstack(
rx.heading(f"Count: {MyState.count}"),
rx.hstack(
rx.button("Increment by 1", on_click=increment(1)),
rx.button("Increment by 5", on_click=increment(5)),
rx.button("Increment by 10", on_click=increment(10)),
),
spacing="4",
align="center",
)
In this example:
MyState class with a count variableincrement that takes a MyState instance as its first parameterHere's a comparison between traditional event handlers defined within state classes and decentralized event handlers:
# Traditional event handler within a state class
class TraditionalState(rx.State):
count: int = 0
@rx.event
def increment(self, amount: int = 1):
self.count += amount
# Usage in components
rx.button("Increment", on_click=TraditionalState.increment(5))
# Decentralized event handler outside the state class
class DecentralizedState(rx.State):
count: int = 0
@rx.event
def increment(state: DecentralizedState, amount: int = 1):
state.count += amount
# Usage in components
rx.button("Increment", on_click=increment(5))
Key differences:
self to reference the state instance@rx.event respectivelyDecentralized event handlers are particularly useful in these scenarios:
Always use proper type annotations for your state parameter and any additional parameters:
@rx.event
def update_user(state: UserState, name: str, age: int):
state.name = name
state.age = age
Follow these naming conventions for clarity:
state or the first letter of the state class)Consider these approaches for organizing decentralized event handlers:
events directory with files organized by feature# Example organization in a larger application
# events/user_events.py
@rx.event
def update_user(state: UserState, name: str, age: int):
state.name = name
state.age = age
@rx.event
def delete_user(state: UserState):
state.name = ""
state.age = 0
Decentralized event handlers work seamlessly with other Reflex event features:
# Background event
@rx.event(background=True)
async def long_running_task(state: AppState):
# Long-running task implementation
pass
# Event chaining
@rx.event
def process_form(state: FormState, data: dict):
# Process form data
return validate_data # Chain to another event