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 ofElement
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 otherElement
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. TheElement
constructor function also has the side-effect of inserting itself to the renderedElement
tree, as a child of thewith
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 anElement
to be able to use Hooks such asuse_state()
, since those are bound to anElement
.