Skip to content

component

wybthon.component

@component decorator and forward_ref for function components.

The @component decorator converts each function parameter into a reactive getter backed by a Signal. This means prop changes from a parent automatically propagate without boilerplate. The component body always runs once (setup phase). To produce dynamic output, return a render function that will be re-invoked whenever a tracked signal (including a prop getter) changes.

Reactive prop getters

Each named parameter in the decorated function is replaced by a zero-argument getter function. Call it to read the current value::

@component
def Greeting(name="world"):
    def render():
        return p(f"Hello, {name()}!")
    return render

The getter is backed by a Signal that the reconciler updates whenever the parent provides new prop values.

component(fn)

Decorator that turns function parameters into reactive prop getters.

Stateful -- create signals during setup and return a render function (setup runs once, render re-runs when signals change)::

@component
def Counter(initial=0):
    count, set_count = create_signal(initial())
    def render():
        return div(p(f"Count: {count()}"),
                   button("+", on_click=lambda e: set_count(count() + 1)))
    return render

Stateless -- return a VNode directly. The body is auto-wrapped as a render function and re-called when prop signals change::

@component
def Greeting(name="world"):
    return p(f"Hello, {name()}!")

Children are available via a children parameter::

@component
def Card(title="", children=None):
    def render():
        kids = children() or []
        if not isinstance(kids, list):
            kids = [kids]
        return section(h3(title()), *kids)
    return render

Direct calls with keyword arguments return a VNode::

Counter(initial=5)
Card("child1", "child2", title="My Card")

The component still works with h() as usual::

h(Counter, {"initial": 5})

forward_ref(render_fn)

Create a component that forwards a ref prop to a child element.

The wrapped function receives (props, ref) instead of (props,), where ref is the value of the ref prop (or None).

Example::

FancyInput = forward_ref(lambda props, ref: input_(
    type="text", ref=ref, class_name="fancy", **props,
))

@component

Decorator that enables Pythonic keyword-argument props for function components.

Stateless — return a VNode directly:

from wybthon import component, p

@component
def Greeting(name: str = "world"):
    return p(f"Hello, {name()}!")

Stateful — create signals and return a render function:

from wybthon import component, create_signal, div, p

@component
def Counter(initial: int = 0):
    count, set_count = create_signal(initial())
    def render():
        return div(p(f"Count: {count()}"))
    return render

Children are available via a children parameter (also a getter):

@component
def Card(title: str = "", children=None):
    kids = children()
    kids = kids if isinstance(kids, list) else ([kids] if kids else [])
    return section(h3(title()), *kids)

Direct calls with keyword arguments return a VNode:

Counter(initial=5)
Card("child1", "child2", title="My Card")

The component still works with h():

h(Counter, {"initial": 5})

forward_ref

forward_ref(render_fn) creates a component that receives a ref prop and forwards it to a child element.

The wrapped function receives (props, ref) instead of (props,).

from wybthon import forward_ref, h

FancyInput = forward_ref(lambda props, ref: h("input", {"type": "text", "ref": ref, **props}))

# Usage
h(FancyInput, {"ref": my_ref, "placeholder": "Type here..."})