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

Fix double rendering #46

Merged
merged 5 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 14 additions & 7 deletions src/reactpy_router/routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Archmonger marked this conversation as resolved.
Show resolved Hide resolved

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."""
Expand Down
62 changes: 62 additions & 0 deletions tests/test_rendering.py
Original file line number Diff line number Diff line change
@@ -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
Archmonger marked this conversation as resolved.
Show resolved Hide resolved

@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
Empty file added tests/tooling/__init__.py
Empty file.
7 changes: 7 additions & 0 deletions tests/tooling/page.py
Original file line number Diff line number Diff line change
@@ -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")
Archmonger marked this conversation as resolved.
Show resolved Hide resolved