Browse Source

Format component as React string (#1848)

Nikhil Rao 1 year ago
parent
commit
ac8dfc5f91

+ 2 - 0
reflex/.templates/jinja/web/pages/component.js.jinja2

@@ -0,0 +1,2 @@
+{% import 'web/pages/utils.js.jinja2' as utils %}
+{{utils.render(component.render())}}

+ 12 - 0
reflex/compiler/compiler.py

@@ -170,6 +170,18 @@ def _compile_root_stylesheet(stylesheets: List[str]) -> str:
     return templates.STYLE.render(stylesheets=sheets)
 
 
+def _compile_component(component: Component) -> str:
+    """Compile a single component.
+
+    Args:
+        component: The component to compile.
+
+    Returns:
+        The compiled component.
+    """
+    return templates.COMPONENT.render(component=component)
+
+
 def _compile_components(components: Set[CustomComponent]) -> str:
     """Compile the components.
 

+ 3 - 0
reflex/compiler/templates.py

@@ -69,6 +69,9 @@ CONTEXT = get_template("web/utils/context.js.jinja2")
 # Template for Tailwind config.
 TAILWIND_CONFIG = get_template("web/tailwind.config.js.jinja2")
 
+# Template to render a component tag.
+COMPONENT = get_template("web/pages/component.js.jinja2")
+
 # Code to render a single NextJS page.
 PAGE = get_template("web/pages/index.js.jinja2")
 

+ 3 - 1
reflex/components/component.py

@@ -317,7 +317,9 @@ class Component(Base, ABC):
         Returns:
             The code to render the component.
         """
-        return format.json_dumps(self.render())
+        from reflex.compiler.compiler import _compile_component
+
+        return _compile_component(self)
 
     def _render(self) -> Tag:
         """Define how to render the component in React.

+ 20 - 0
tests/components/test_component.py

@@ -534,3 +534,23 @@ def test_component_with_only_valid_children(fixture, request):
         == f"The component `{component.__name__}` only allows the components: `Text` as children. "
         f"Got `Box` instead."
     )
+
+
+@pytest.mark.parametrize(
+    "component,rendered",
+    [
+        (rx.text("hi"), "<Text>\n  {`hi`}\n</Text>"),
+        (
+            rx.box(rx.heading("test", size="md")),
+            "<Box>\n  <Heading size={`md`}>\n  {`test`}\n</Heading>\n</Box>",
+        ),
+    ],
+)
+def test_format_component(component, rendered):
+    """Test that a component is formatted correctly.
+
+    Args:
+        component: The component to format.
+        rendered: The expected rendered component.
+    """
+    assert str(component) == rendered