Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate get_hooks and get_hooks_internal for stable output #2710

Merged
merged 7 commits into from
Mar 15, 2024
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
{% import 'web/pages/utils.js.jinja2' as utils %}

export function {{tag_name}} () {
{% for hook in component.get_hooks() %}
{% for hook in component.get_hooks_internal() %}
{{ hook }}
{% endfor %}

{% for hook in memo_trigger_hooks %}
{{ hook }}
{% endfor %}

{% for hook in component.get_hooks() %}
{{ hook }}
{% endfor %}

return (
{{utils.render(component.render(), indent_width=0)}}
)
Expand Down
4 changes: 2 additions & 2 deletions reflex/compiler/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def _compile_app(app_root: Component) -> str:
return templates.APP_ROOT.render(
imports=utils.compile_imports(app_root.get_imports()),
custom_codes=app_root.get_custom_code(),
hooks=app_root.get_hooks(),
hooks=app_root.get_hooks_internal() | app_root.get_hooks(),
render=app_root.render(),
)

Expand Down Expand Up @@ -119,7 +119,7 @@ def _compile_page(
imports=imports,
dynamic_imports=component.get_dynamic_imports(),
custom_codes=component.get_custom_code(),
hooks=component.get_hooks(),
hooks=component.get_hooks_internal() | component.get_hooks(),
render=component.render(),
**kwargs,
)
Expand Down
2 changes: 1 addition & 1 deletion reflex/compiler/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def compile_custom_component(
"name": component.tag,
"props": props,
"render": render.render(),
"hooks": render.get_hooks(),
"hooks": render.get_hooks_internal() | render.get_hooks(),
"custom_code": render.get_custom_code(),
},
imports,
Expand Down
36 changes: 33 additions & 3 deletions reflex/components/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ def render(self) -> dict:
The dictionary for template of the component.
"""

@abstractmethod
def get_hooks_internal(self) -> set[str]:
"""Get the reflex internal hooks for the component and its children.

Returns:
The code that should appear just before user-defined hooks.
"""

@abstractmethod
def get_hooks(self) -> set[str]:
"""Get the React hooks for this component.
Expand Down Expand Up @@ -1141,14 +1149,28 @@ def _get_hooks(self) -> str | None:
"""
return

def get_hooks_internal(self) -> set[str]:
"""Get the reflex internal hooks for the component and its children.

Returns:
The code that should appear just before user-defined hooks.
"""
# Store the code in a set to avoid duplicates.
code = self._get_hooks_internal()

# Add the hook code for the children.
for child in self.children:
code |= child.get_hooks_internal()

return code

def get_hooks(self) -> Set[str]:
"""Get the React hooks for this component and its children.

Returns:
The code that should appear just before returning the rendered component.
"""
# Store the code in a set to avoid duplicates.
code = self._get_hooks_internal()
code = set()

# Add the hook code for this component.
hooks = self._get_hooks()
Expand Down Expand Up @@ -1785,6 +1807,14 @@ def _get_memoized_event_triggers(
)
return trigger_memo

def get_hooks_internal(self) -> set[str]:
"""Get the reflex internal hooks for the component and its children.

Returns:
The code that should appear just before user-defined hooks.
"""
return set()

def get_hooks(self) -> set[str]:
"""Get the React hooks for this component.

Expand Down Expand Up @@ -1893,7 +1923,7 @@ def create(cls, *children, **props) -> Component:
The memoization leaf
"""
comp = super().create(*children, **props)
if comp.get_hooks():
if comp.get_hooks() or comp.get_hooks_internal():
comp._memoization_mode = cls._memoization_mode.copy(
update={"disposition": MemoizationDisposition.ALWAYS}
)
Expand Down
2 changes: 1 addition & 1 deletion reflex/components/el/elements/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def create(cls, *children, **props):
props["handle_submit_unique_name"] = ""
form = super().create(*children, **props)
form.handle_submit_unique_name = md5(
str(form.get_hooks()).encode("utf-8")
str(form.get_hooks_internal().union(form.get_hooks())).encode("utf-8")
).hexdigest()
return form

Expand Down
6 changes: 4 additions & 2 deletions reflex/components/markdown/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,10 @@ def _get_component_map_name(self) -> str:

def _get_custom_code(self) -> str | None:
hooks = set()
for component in self.component_map.values():
hooks |= component(_MOCK_ARG).get_hooks()
for _component in self.component_map.values():
comp = _component(_MOCK_ARG)
hooks |= comp.get_hooks_internal()
hooks |= comp.get_hooks()
formatted_hooks = "\n".join(hooks)
return f"""
function {self._get_component_map_name()} () {{
Expand Down
Loading