Skip to content

Events and forms

Use snake_case DOM props such as on_click, on_change and on_key_down. Handlers may accept the browser event or no arguments:

html.button("Save", on_click=lambda: save())
html.input(value=text, on_change=lambda event: set_text(str(event.target.value)))

A complete controlled form

from pyreact_forge import component, html, use_state

@component
def App():
    name, set_name = use_state("")
    message, set_message = use_state("")

    def submit(event):
        event.preventDefault()
        set_message(f"Hello, {name.strip() or 'friend'}")

    return html.form(
        html.label("Name", html_for="name"),
        html.input(id="name", value=name,
                   on_change=lambda event: set_name(str(event.target.value))),
        html.button("Greet", type="submit"),
        html.p(message, role="status"),
        on_submit=submit,
    )

Use checked and event.target.checked for controlled checkboxes. Keep labels associated with controls, use explicit button types inside forms and report errors in text rather than color alone.

Async form actions

use_action_state(action, initial) returns the result state, a dispatch/action callback and a pending flag. A form's action can use that callback; the action receives (previous_state, form_data). Its form_data is a browser FormData proxy. use_form_status must be called from a component inside the form.

The action can be an async Python function. It executes in the browser; it is not a trusted server action. Use an authenticated backend endpoint when the operation requires authorization or private credentials.

For a tested action/optimistic example, see examples/conformance/app.py in the repository and the async guide.