From 590a24e3c1da334edf83c03d7edbfc605d1fd3c6 Mon Sep 17 00:00:00 2001 From: Steve Jones Date: Sat, 16 Nov 2024 16:23:18 +0000 Subject: [PATCH 1/5] Fix double rendering issue on initial page load --- src/reactpy_router/routers.py | 21 ++++++++---- tests/test_rendering.py | 62 +++++++++++++++++++++++++++++++++++ tests/tooling/__init__.py | 0 tests/tooling/page.py | 7 ++++ 4 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 tests/test_rendering.py create mode 100644 tests/tooling/__init__.py create mode 100644 tests/tooling/page.py diff --git a/src/reactpy_router/routers.py b/src/reactpy_router/routers.py index abdbc5e..7ff181f 100644 --- a/src/reactpy_router/routers.py +++ b/src/reactpy_router/routers.py @@ -74,13 +74,20 @@ def router( match = use_memo(lambda: _match_route(resolvers, location, select="first")) if match: - route_elements = [ - _route_state_context( - element, - value=RouteState(set_location, params), - ) - for element, params in match - ] + # We need skip rendering the application on 'first_load' to avoid + # rendering it twice. The second render occurs following + # the impending on_history_change event + + if first_load: + route_elements = [] + else: + route_elements = [ + _route_state_context( + element, + value=RouteState(set_location, params), + ) + for element, params in match + ] def on_history_change(event: dict[str, Any]) -> None: """Callback function used within the JavaScript `History` component.""" diff --git a/tests/test_rendering.py b/tests/test_rendering.py new file mode 100644 index 0000000..39ae6de --- /dev/null +++ b/tests/test_rendering.py @@ -0,0 +1,62 @@ +import pytest +from reactpy import component, html +from reactpy.testing import DisplayFixture + +from reactpy_router import browser_router, route + +from .tooling.page import page_stable + + +@pytest.mark.anyio +async def test_router_simple(display: DisplayFixture): + """Confirm the number of rendering operations when new pages are first loaded""" + root_render_count = 0 + home_page_render_count = 0 + not_found_render_count = 0 + + @component + def root(): + nonlocal root_render_count + root_render_count += 1 + + # https://reactive-python.github.io/reactpy-router/latest/#quick-start + + @component + def home_page(): + nonlocal home_page_render_count + home_page_render_count += 1 + return html.h1("Home Page 🏠") + + @component + def not_found(): + nonlocal not_found_render_count + not_found_render_count += 1 + return html.h1("Missing Link 🔗‍💥") + + return browser_router( + route("/", home_page()), + route("{404:any}", not_found()), + ) + + await display.show(root) + await page_stable(display.page) + + assert root_render_count == 1 + assert home_page_render_count == 1 + assert not_found_render_count == 0 + + await display.goto("/xxx") + await page_stable(display.page) + + assert root_render_count == 2 + assert home_page_render_count == 1 + assert not_found_render_count == 1 + + await display.goto("/yyy") + await page_stable(display.page) + + assert root_render_count == 3 + assert home_page_render_count == 1 + assert not_found_render_count == 2 + + assert True diff --git a/tests/tooling/__init__.py b/tests/tooling/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/tooling/page.py b/tests/tooling/page.py new file mode 100644 index 0000000..84f178a --- /dev/null +++ b/tests/tooling/page.py @@ -0,0 +1,7 @@ +from playwright.async_api._generated import Page + + +async def page_stable(page: Page) -> None: + """Only return when network is idle and DOM has loaded""" + await page.wait_for_load_state("networkidle") + await page.wait_for_load_state("domcontentloaded") From 05a9eb7141ea8f278ff490dd828154a3a4b8059b Mon Sep 17 00:00:00 2001 From: Steve Jones Date: Sat, 16 Nov 2024 16:27:40 +0000 Subject: [PATCH 2/5] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26a01ca..f9cc516 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,7 @@ Using the following categories, list your changes in this order: ## [Unreleased] -- Nothing (yet)! +- Fix double rendering issue on initial page load ## [1.0.2] - 2024-10-24 From 96f6f81e7898522f0f24c414cac61c215f23f0d7 Mon Sep 17 00:00:00 2001 From: Steve Jones Date: Sun, 17 Nov 2024 09:59:15 +0000 Subject: [PATCH 3/5] PR #46, review changes --- src/reactpy_router/routers.py | 8 +++++--- tests/test_rendering.py | 4 +--- tests/tooling/__init__.py | 0 tests/{tooling/page.py => utils.py} | 0 4 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 tests/tooling/__init__.py rename tests/{tooling/page.py => utils.py} (100%) diff --git a/src/reactpy_router/routers.py b/src/reactpy_router/routers.py index 7ff181f..6cec24c 100644 --- a/src/reactpy_router/routers.py +++ b/src/reactpy_router/routers.py @@ -74,11 +74,13 @@ def router( match = use_memo(lambda: _match_route(resolvers, location, select="first")) if match: - # We need skip rendering the application on 'first_load' to avoid - # rendering it twice. The second render occurs following - # the impending on_history_change event if first_load: + + # We need skip rendering the application on 'first_load' to avoid + # rendering it twice. The second render occurs following + # the impending on_history_change event + route_elements = [] else: route_elements = [ diff --git a/tests/test_rendering.py b/tests/test_rendering.py index 39ae6de..70d99e4 100644 --- a/tests/test_rendering.py +++ b/tests/test_rendering.py @@ -4,7 +4,7 @@ from reactpy_router import browser_router, route -from .tooling.page import page_stable +from .utils import page_stable @pytest.mark.anyio @@ -19,8 +19,6 @@ def root(): nonlocal root_render_count root_render_count += 1 - # https://reactive-python.github.io/reactpy-router/latest/#quick-start - @component def home_page(): nonlocal home_page_render_count diff --git a/tests/tooling/__init__.py b/tests/tooling/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/tooling/page.py b/tests/utils.py similarity index 100% rename from tests/tooling/page.py rename to tests/utils.py From b284987ec766d44fd5c8f8227caf87ce2a6cbe59 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:49:44 -0800 Subject: [PATCH 4/5] remove excess whitespace --- src/reactpy_router/routers.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/reactpy_router/routers.py b/src/reactpy_router/routers.py index 6cec24c..d8e75f2 100644 --- a/src/reactpy_router/routers.py +++ b/src/reactpy_router/routers.py @@ -74,13 +74,10 @@ def router( match = use_memo(lambda: _match_route(resolvers, location, select="first")) if match: - if first_load: - # We need skip rendering the application on 'first_load' to avoid # rendering it twice. The second render occurs following # the impending on_history_change event - route_elements = [] else: route_elements = [ From 1ee32a750e35c9c0ade6f1a5f9d6192130730bcd Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:52:16 -0800 Subject: [PATCH 5/5] rename util --- tests/test_rendering.py | 8 ++++---- tests/utils.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_rendering.py b/tests/test_rendering.py index 70d99e4..6a78ecc 100644 --- a/tests/test_rendering.py +++ b/tests/test_rendering.py @@ -4,7 +4,7 @@ from reactpy_router import browser_router, route -from .utils import page_stable +from .utils import page_load_complete @pytest.mark.anyio @@ -37,21 +37,21 @@ def not_found(): ) await display.show(root) - await page_stable(display.page) + await page_load_complete(display.page) assert root_render_count == 1 assert home_page_render_count == 1 assert not_found_render_count == 0 await display.goto("/xxx") - await page_stable(display.page) + await page_load_complete(display.page) assert root_render_count == 2 assert home_page_render_count == 1 assert not_found_render_count == 1 await display.goto("/yyy") - await page_stable(display.page) + await page_load_complete(display.page) assert root_render_count == 3 assert home_page_render_count == 1 diff --git a/tests/utils.py b/tests/utils.py index 84f178a..2b7bc2e 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,7 +1,7 @@ from playwright.async_api._generated import Page -async def page_stable(page: Page) -> None: +async def page_load_complete(page: Page) -> None: """Only return when network is idle and DOM has loaded""" await page.wait_for_load_state("networkidle") await page.wait_for_load_state("domcontentloaded")