Open guidocalvano opened 4 months ago
Note that this means no cyclic references between states and thus no recursion. So you wouldn't be able to make redit, because redit contains a tree structure, which is recursive.
Using rx.cond also doesn't fix this...
@guidocalvano I was looking a bit into this yesterday. There's a couple fixes we need to make to the framework to fully support this, but the code below avoids the infinite recursion:
import reflex as rx
from typing import List
class ASTNodeState(rx.Base):
key: str = "unknown"
type: str = "unknown"
text: str = "loading"
children: List["ASTNodeState"] = []
class ASTNodeView(rx.ComponentState):
@classmethod
def get_component(
cls, children: List[ASTNodeState], key: str, type: str, text: str
) -> rx.Component:
# need to convert it to a var and specify the type.
children = rx.Var.create(children).to(list[ASTNodeState])
return rx.chakra.span(
rx.text(key),
rx.chakra.text(type),
rx.chakra.text(text),
rx.foreach(children, render_child),
)
ast_node_view = ASTNodeView.create
# rx.memo pulls the function into it's own definition, avoiding the infinite recursion
@rx.memo
def ast_node(children: List[ASTNodeState], key: str, type: str, text: str):
return ast_node_view(key=key, type=type, text=text, children=children)
def render_child(item: ASTNodeState):
return ast_node(
key=item.key, type=item.type, text=item.text, children=item.children
)
def index() -> rx.Component:
return rx.fragment(
ast_node_view([
ASTNodeState(key="1", type="type1", text="text1", children=[
ASTNodeState(key="1.1", type="type1", text="text1", children=[
]),
]),
], key="root", type="root", text="root"),
)
app = rx.App()
app.add_page(index)
The recursion is caused because by default Reflex evaluates all the components into one giant component for the page. Using @rx.memo
pulls out the component into its own function instead of evaluating it. There's one bug we need to fix #3438 to fix the serialization and then this should work.
The @rx.memo
isn't documented much because it was kind of a hack we needed. We're planning on cleaning it up and documenting it in the future.
Can I work on this issue?
@shauryaryan just assigned you to it - this one may be a bit hard, let us know if you need any help going through it
Describe the bug I tried to render a tree, but kept getting missing attribute errors whenever I had a ForwardRef in my state.
To Reproduce Steps to reproduce the behavior:
class ASTNodeState(rx.Base): key: str = "unknown" type: str = "unknown" text: str = "loading" children: List["ASTNodeState"] = []
class ASTNodeView(rx.ComponentState):
ast_node_view = ASTNodeView.create
def render_child(item: ASTNodeState):
hack to make recursion possible, this leads to an infinite loop in some deep copy function