Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion reflex/compiler/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,11 @@ def _get_shared_components_recursive(
# When the component is referenced by more than one page, render it
# to be included in the STATEFUL_COMPONENTS module.
# Skip this step in dev mode, thereby avoiding potential hot reload errors for larger apps
if isinstance(component, StatefulComponent) and component.references > 1:
if (
isinstance(component, StatefulComponent)
and component.references > 1
and is_prod_mode()
):
# Reset this flag to render the actual component.
component.rendered_as_shared = False

Expand Down
33 changes: 33 additions & 0 deletions tests/units/compiler/test_compiler.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import importlib.util
import os
from pathlib import Path
from unittest.mock import patch

import pytest
from pytest_mock import MockerFixture

from reflex import constants
from reflex.compiler import compiler, utils
from reflex.components.base import document
from reflex.components.component import StatefulComponent
from reflex.components.el.elements.metadata import Link
from reflex.constants.compiler import PageNames
from reflex.utils.imports import ImportVar, ParsedImportDict
Expand Down Expand Up @@ -448,3 +450,34 @@ def test_create_document_root_with_meta_viewport():
assert str(root.children[0].children[2].name) == '"viewport"' # pyright: ignore [reportAttributeAccessIssue]
assert str(root.children[0].children[2].content) == '"foo"' # pyright: ignore [reportAttributeAccessIssue]
assert str(root.children[0].children[3].char_set) == '"utf-8"' # pyright: ignore [reportAttributeAccessIssue]


@pytest.mark.parametrize("prod_mode", [True, False])
def test_shared_stateful_components_only_in_prod(prod_mode: bool):
"""Shared stateful components must only be marked rendered_as_shared in prod mode.

In dev mode, stateful component compilation is skipped so the shared module
is empty. Marking components as rendered_as_shared in dev mode causes them to
import from a non-existent module, silently breaking rendering.

Args:
prod_mode: Whether to simulate prod mode.
"""
from reflex.components.component import Component

component = StatefulComponent(
tag="TestComponent",
references=2, # referenced by more than one page
children=[],
component=Component.create(),
)

rendered_components: dict[str, None] = {}
all_import_dicts: list[ParsedImportDict] = []

with patch("reflex.compiler.compiler.is_prod_mode", return_value=prod_mode):
compiler._get_shared_components_recursive(
component, rendered_components, all_import_dicts
)

assert component.rendered_as_shared is prod_mode
Loading