Skip to content

Commit

Permalink
fix tag render to be recursive (#4714)
Browse files Browse the repository at this point in the history
  • Loading branch information
adhami3310 authored Jan 29, 2025
1 parent 1e8e82e commit 2c3257d
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 28 deletions.
2 changes: 1 addition & 1 deletion reflex/.templates/jinja/web/pages/utils.js.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
{% for condition in case[:-1] %}
case JSON.stringify({{ condition._js_expr }}):
{% endfor %}
return {{ case[-1] }};
return {{ render(case[-1]) }};
break;
{% endfor %}
default:
Expand Down
4 changes: 2 additions & 2 deletions reflex/components/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -2389,7 +2389,7 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->
if tag["name"] == "match":
element = tag["cond"]

conditionals = tag["default"]
conditionals = render_dict_to_var(tag["default"], imported_names)

for case in tag["match_cases"][::-1]:
condition = case[0].to_string() == element.to_string()
Expand All @@ -2398,7 +2398,7 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->

conditionals = ternary_operation(
condition,
case[-1],
render_dict_to_var(case[-1], imported_names),
conditionals,
)

Expand Down
43 changes: 24 additions & 19 deletions reflex/components/tags/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,33 @@
from __future__ import annotations

import dataclasses
from typing import Any, Dict, List, Optional, Union
from typing import Any, Dict, List, Optional, Sequence, Union

from reflex.event import EventChain
from reflex.utils import format, types
from reflex.vars.base import LiteralVar, Var


def render_prop(value: Any) -> Any:
"""Render the prop.
Args:
value: The value to render.
Returns:
The rendered value.
"""
from reflex.components.component import BaseComponent

if isinstance(value, BaseComponent):
return value.render()
if isinstance(value, Sequence) and not isinstance(value, str):
return [render_prop(v) for v in value]
if callable(value) and not isinstance(value, Var):
return None
return value


@dataclasses.dataclass()
class Tag:
"""A React tag."""
Expand Down Expand Up @@ -65,25 +85,10 @@ def __iter__(self):
Yields:
Tuple[str, Any]: The field name and value.
"""
from reflex.components.component import BaseComponent

for field in dataclasses.fields(self):
value = getattr(self, field.name)
if isinstance(value, list):
children = []
for child in value:
if isinstance(child, BaseComponent):
children.append(child.render())
else:
children.append(child)
yield field.name, children
continue
if isinstance(value, BaseComponent):
yield field.name, value.render()
continue
if callable(value) and not isinstance(value, Var):
continue
yield field.name, getattr(self, field.name)
rendered_value = render_prop(getattr(self, field.name))
if rendered_value is not None:
yield field.name, rendered_value

def add_props(self, **kwargs: Optional[Any]) -> Tag:
"""Add props to the tag.
Expand Down
12 changes: 6 additions & 6 deletions tests/units/components/core/test_match.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,39 +42,39 @@ def test_match_components():

assert match_cases[0][0]._js_expr == "1"
assert match_cases[0][0]._var_type is int
first_return_value_render = match_cases[0][1].render()
first_return_value_render = match_cases[0][1]
assert first_return_value_render["name"] == "RadixThemesText"
assert first_return_value_render["children"][0]["contents"] == '{"first value"}'

assert match_cases[1][0]._js_expr == "2"
assert match_cases[1][0]._var_type is int
assert match_cases[1][1]._js_expr == "3"
assert match_cases[1][1]._var_type is int
second_return_value_render = match_cases[1][2].render()
second_return_value_render = match_cases[1][2]
assert second_return_value_render["name"] == "RadixThemesText"
assert second_return_value_render["children"][0]["contents"] == '{"second value"}'

assert match_cases[2][0]._js_expr == "[1, 2]"
assert match_cases[2][0]._var_type == List[int]
third_return_value_render = match_cases[2][1].render()
third_return_value_render = match_cases[2][1]
assert third_return_value_render["name"] == "RadixThemesText"
assert third_return_value_render["children"][0]["contents"] == '{"third value"}'

assert match_cases[3][0]._js_expr == '"random"'
assert match_cases[3][0]._var_type is str
fourth_return_value_render = match_cases[3][1].render()
fourth_return_value_render = match_cases[3][1]
assert fourth_return_value_render["name"] == "RadixThemesText"
assert fourth_return_value_render["children"][0]["contents"] == '{"fourth value"}'

assert match_cases[4][0]._js_expr == '({ ["foo"] : "bar" })'
assert match_cases[4][0]._var_type == Mapping[str, str]
fifth_return_value_render = match_cases[4][1].render()
fifth_return_value_render = match_cases[4][1]
assert fifth_return_value_render["name"] == "RadixThemesText"
assert fifth_return_value_render["children"][0]["contents"] == '{"fifth value"}'

assert match_cases[5][0]._js_expr == f"({MatchState.get_name()}.num + 1)"
assert match_cases[5][0]._var_type is int
fifth_return_value_render = match_cases[5][1].render()
fifth_return_value_render = match_cases[5][1]
assert fifth_return_value_render["name"] == "RadixThemesText"
assert fifth_return_value_render["children"][0]["contents"] == '{"sixth value"}'

Expand Down

0 comments on commit 2c3257d

Please sign in to comment.