edifice.component

edifice.component#

class edifice.component(f)[source]#

Bases:

Decorator turning a render function of props into an Element.

The component will be re-rendered when its props are not __eq__ to the props from the last time the component rendered.

The component function must render exactly one Element. In the component function, declare a tree of Element with a single root:

@component
def MySimpleComp(self, prop1, prop2, prop3):
    with View():
        Label(prop1)
        Label(prop2)
        Label(prop3)

To declare an Element to be the parent of some other Element s in the tree, use the parent as a with statement context manager.

To introduce state into a component, use Hooks.

Each Element is actually implemented as the constructor function for a Python class. The Element constructor function also has the side-effect of inserting itself to the rendered Element tree, as a child of the with context layout Element.

For that reason, you have to be careful about binding Elements to variables and passing them around. They will insert themselves at the time they are created. This code will NOT declare the intended Element tree, same as the code above:

@component
def MySimpleComp(self, prop1, prop2, prop3):
    label3 = Label(prop3)
    with View():
        Label(prop1)
        Label(prop2)
        label3

To solve this, defer the construction of the Element with a lambda function. This code will declare the same intended Element tree as the code above:

@component
def MySimpleComp(self, prop1, prop2, prop3):
    label3 = lambda: Label(prop3)
    with View():
        Label(prop1)
        Label(prop2)
        label3()

If these component Elements are render functions, then why couldn’t we just write a normal render function with no decorator:

# No decorator
def MySimpleComp(prop1, prop2, prop3):
    with View():
        Label(prop1)
        Label(prop2)
        Label(prop3)

instead. The difference is, with the decorator, an actual Element object is created, which can be viewed, for example, in the inspector. Moreover, you need an Element to be able to use Hooks such as use_state(), since those are bound to an Element.

Parameters:

f (Callable[[Concatenate[TypeVar(C, bound= Element), ParamSpec(P)]], None]) – the function to wrap. Its first argument must be self. Subsequent arguments are props.

Return type:

Callable[[ParamSpec(P)], Element]