Reactive user interfaces with pure Python
—
Virtual DOM system for efficient component rendering and layout management. ReactPy uses a virtual DOM representation to optimize rendering performance and provide a declarative interface for UI construction.
The vdom function creates virtual DOM elements programmatically:
def vdom(tag: str, *children, **attributes) -> VdomDict: ...Parameters:
tag: HTML/SVG tag name*children: Child elements (strings, other VDOM elements, Components)**attributes: Element attributes as keyword argumentsReturns: VdomDict representing the virtual DOM element
Usage Examples:
from reactpy import vdom
# Basic element
element = vdom("div", "Hello World")
# Element with attributes
styled_element = vdom("div", "Styled content", className="my-class", id="unique")
# Nested elements
nested = vdom("div",
vdom("h1", "Title"),
vdom("p", "Paragraph content"),
vdom("button", "Click me", onClick=handler)
)Create custom element constructors:
def make_vdom_constructor(tag: str, allow_children: bool = True) -> Callable[..., VdomDict]: ...Parameters:
tag: HTML/SVG tag nameallow_children: Whether the element can have childrenReturns: Constructor function for the element
Usage Examples:
# Create custom constructors
my_div = make_vdom_constructor("div")
my_img = make_vdom_constructor("img", allow_children=False)
# Use custom constructors
content = my_div(
{"className": "container"},
my_img({"src": "image.jpg", "alt": "Description"})
)Validate VDOM structure:
def validate_vdom_json(value: Any) -> VdomDict: ...Parameters:
value: Value to validate as VDOMReturns: Validated VdomDict
Raises: ValidationError if invalid
Convert between HTML strings and VDOM:
def html_to_vdom(html_string: str) -> VdomDict: ...
def vdom_to_html(vdom_dict: VdomDict) -> str: ...Usage Examples:
# Convert HTML to VDOM
html_str = "<div class='container'><h1>Title</h1></div>"
vdom_element = html_to_vdom(html_str)
# Convert VDOM to HTML
vdom_element = vdom("div", vdom("h1", "Title"), className="container")
html_output = vdom_to_html(vdom_element)The Layout class manages component rendering and updates:
class Layout:
def __init__(self, component: ComponentType) -> None: ...
async def render() -> LayoutUpdate: ...
async def deliver(event: LayoutEvent) -> None: ...Methods:
render(): Render component tree and return layout updatedeliver(event): Deliver event to appropriate componentUsage Examples:
from reactpy.core.layout import Layout
@component
def MyComponent():
return html.h1("Hello Layout!")
layout = Layout(MyComponent)
# Render the layout
update = await layout.render()
# Handle events
event = {
"type": "click",
"target": {"id": "button1"},
"clientX": 100,
"clientY": 50
}
await layout.deliver(event)Type definitions for layout system:
# Layout update message
class LayoutUpdate(TypedDict):
type: Literal["layout-update"]
body: dict[str, Any]
# Layout event message
class LayoutEvent(TypedDict):
type: Literal["layout-event"]
target: str
data: dict[str, Any]
# Layout update body structure
class LayoutUpdateBody(TypedDict):
root: VdomDict
mutations: list[dict[str, Any]]
event_handlers: dict[str, str]VdomDict structure for virtual DOM elements:
class VdomDict(TypedDict):
tagName: str
children: list[VdomChild]
attributes: dict[str, Any]
eventHandlers: dict[str, EventHandler]
key: str | NoneUsage Examples:
# Manual VDOM construction
vdom_element = {
"tagName": "div",
"attributes": {"className": "container", "id": "main"},
"children": [
"Text content",
{
"tagName": "button",
"attributes": {"type": "button"},
"children": ["Click me"],
"eventHandlers": {"onClick": event_handler},
"key": None
}
],
"eventHandlers": {},
"key": None
}Understanding the rendering process:
@component
def RenderingExample():
# 1. Component function is called
# 2. Hooks are executed (state, effects, etc.)
# 3. VDOM is returned
# 4. Layout processes VDOM
# 5. Differences are calculated
# 6. Updates are sent to client
count, set_count = use_state(0) # Hook execution
return html.div( # VDOM creation
html.h1(f"Count: {count}"),
html.button(
{"onClick": lambda: set_count(count + 1)},
"Increment"
)
)VDOM enables efficient updates:
@component
def OptimizedList(items):
# Keys help VDOM identify which items changed
return html.ul(
*[
html.li(item["text"], key=item["id"])
for item in items
]
)
@component
def MemoizedComponent():
expensive_value = use_memo(
lambda: expensive_computation(),
[] # Empty deps = compute once
)
# VDOM only updates when expensive_value changes
return html.div(f"Result: {expensive_value}")VDOM validation and error handling:
from reactpy.core.vdom import validate_vdom_json
try:
# Validate VDOM structure
valid_vdom = validate_vdom_json({
"tagName": "div",
"children": ["content"],
"attributes": {}
})
except ValidationError as e:
print(f"Invalid VDOM: {e}")
# Common VDOM errors:
# - Missing required keys (tagName, children, attributes)
# - Invalid children types
# - Circular references
# - Invalid attribute valuesInstall with Tessl CLI
npx tessl i tessl/pypi-reactpy