diff --git a/docs/examples/python/use_params.py b/docs/examples/python/use_params.py index 93a4f07..90aab5d 100644 --- a/docs/examples/python/use_params.py +++ b/docs/examples/python/use_params.py @@ -6,7 +6,7 @@ @component def user(): params = use_params() - return html._(html.h1(f"User {params['id']} 👤"), html.p("Nothing (yet).")) + return html(html.h1(f"User {params['id']} 👤"), html.p("Nothing (yet).")) @component diff --git a/docs/examples/python/use_search_params.py b/docs/examples/python/use_search_params.py index faeba5e..8420d8c 100644 --- a/docs/examples/python/use_search_params.py +++ b/docs/examples/python/use_search_params.py @@ -6,7 +6,7 @@ @component def search(): search_params = use_search_params() - return html._(html.h1(f"Search Results for {search_params['query'][0]} 🔍"), html.p("Nothing (yet).")) + return html(html.h1(f"Search Results for {search_params['query'][0]} 🔍"), html.p("Nothing (yet).")) @component diff --git a/docs/src/learn/routers-routes-and-links.md b/docs/src/learn/routers-routes-and-links.md index f185514..c42989f 100644 --- a/docs/src/learn/routers-routes-and-links.md +++ b/docs/src/learn/routers-routes-and-links.md @@ -9,7 +9,7 @@ The [`browser_router`][reactpy_router.browser_router] component is one possible !!! abstract "Note" The current location is determined based on the browser's current URL and can be found - by checking the [`use_location`][reactpy.backend.hooks.use_location] hook. + by checking the [`use_location`][reactpy.use_location] hook. Here's a basic example showing how to use `#!python browser_router` with two routes. diff --git a/pyproject.toml b/pyproject.toml index f346125..a8d8eb9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,11 @@ classifiers = [ "Environment :: Web Environment", "Typing :: Typed", ] -dependencies = ["reactpy>=1.1.0, <2.0.0", "typing_extensions"] +dependencies = [ + "reactpy[asgi]>=2.0.0b10, <3.0.0", + "typing_extensions", + "jsonpointer==3.*", +] dynamic = ["version"] urls.Changelog = "https://reactive-python.github.io/reactpy-router/latest/about/changelog/" urls.Documentation = "https://reactive-python.github.io/reactpy-router/latest/" diff --git a/src/js/src/types.ts b/src/js/src/types.ts index 7144668..8b05409 100644 --- a/src/js/src/types.ts +++ b/src/js/src/types.ts @@ -1,6 +1,6 @@ export interface ReactPyLocation { - pathname: string; - search: string; + path: string; + query_string: string; } export interface HistoryProps { diff --git a/src/js/src/utils.ts b/src/js/src/utils.ts index e3f1dd5..797c0b5 100644 --- a/src/js/src/utils.ts +++ b/src/js/src/utils.ts @@ -2,8 +2,8 @@ import { ReactPyLocation } from "./types"; export function createLocationObject(): ReactPyLocation { return { - pathname: window.location.pathname, - search: window.location.search, + path: window.location.pathname, + query_string: window.location.search, }; } diff --git a/src/reactpy_router/components.py b/src/reactpy_router/components.py index 6a751e7..2fd2811 100644 --- a/src/reactpy_router/components.py +++ b/src/reactpy_router/components.py @@ -5,31 +5,25 @@ from uuid import uuid4 from reactpy import component, html, use_connection, use_ref -from reactpy.backend.types import Location -from reactpy.web.module import export, module_from_file +from reactpy.reactjs import component_from_file +from reactpy.types import Location from reactpy_router.hooks import _use_route_state from reactpy_router.types import Route if TYPE_CHECKING: - from reactpy.core.component import Component - from reactpy.core.types import Key, VdomDict + from reactpy.types import Component, Key, VdomDict -History = export( - module_from_file("reactpy-router", file=Path(__file__).parent / "static" / "bundle.js"), - ("History"), +History = component_from_file( + Path(__file__).parent / "static" / "bundle.js", import_names="History", name="reactpy-router" ) """Client-side portion of history handling""" -Link = export( - module_from_file("reactpy-router", file=Path(__file__).parent / "static" / "bundle.js"), - ("Link"), -) +Link = component_from_file(Path(__file__).parent / "static" / "bundle.js", import_names="Link", name="reactpy-router") """Client-side portion of link handling""" -Navigate = export( - module_from_file("reactpy-router", file=Path(__file__).parent / "static" / "bundle.js"), - ("Navigate"), +Navigate = component_from_file( + Path(__file__).parent / "static" / "bundle.js", import_names="Navigate", name="reactpy-router" ) """Client-side portion of the navigate component""" @@ -74,7 +68,7 @@ def _link(attributes: dict[str, Any], *children: Any) -> VdomDict: def on_click_callback(_event: dict[str, Any]) -> None: set_location(Location(**_event)) - return html._(Link({"onClickCallback": on_click_callback, "linkClass": class_name}), html.a(attrs, *children)) + return html(Link({"onClickCallback": on_click_callback, "linkClass": class_name}), html.a(attrs, *children)) def route(path: str, element: Any | None, *routes: Route) -> Route: @@ -118,7 +112,7 @@ def _navigate(to: str, replace: bool = False) -> VdomDict | None: def on_navigate_callback(_event: dict[str, Any]) -> None: set_location(Location(**_event)) - if location.pathname != pathname: + if location.path != pathname: return Navigate({"onNavigateCallback": on_navigate_callback, "to": to, "replace": replace}) return None diff --git a/src/reactpy_router/hooks.py b/src/reactpy_router/hooks.py index 2480440..70f33b5 100644 --- a/src/reactpy_router/hooks.py +++ b/src/reactpy_router/hooks.py @@ -59,7 +59,7 @@ def use_search_params( A dictionary of the current URL's query string parameters. """ location = use_location() - query_string = location.search[1:] if len(location.search) > 1 else "" + query_string = location.query_string[1:] if len(location.query_string) > 1 else "" # TODO: In order to match `react-router`, this will need to return a tuple of the search params \ # and a function to update them. This is currently not possible without reactpy core having a \ diff --git a/src/reactpy_router/routers.py b/src/reactpy_router/routers.py index fad94eb..9956577 100644 --- a/src/reactpy_router/routers.py +++ b/src/reactpy_router/routers.py @@ -7,9 +7,8 @@ from typing import TYPE_CHECKING, Any, Union, cast from reactpy import component, use_memo, use_state -from reactpy.backend.types import Connection, Location from reactpy.core.hooks import ConnectionContext, use_connection -from reactpy.types import ComponentType, VdomDict +from reactpy.types import Component, Connection, Location, VdomDict from reactpy_router.components import History from reactpy_router.hooks import RouteState, _route_state_context @@ -18,8 +17,6 @@ if TYPE_CHECKING: from collections.abc import Iterator, Sequence - from reactpy.core.component import Component - from reactpy_router.types import CompiledRoute, MatchedRoute, Resolver, Route, Router __all__ = ["browser_router", "create_router"] @@ -105,11 +102,11 @@ def _add_route_key(match: MatchedRoute, key: str | int) -> Any: """Add a key to the VDOM or component on the current route, if it doesn't already have one.""" element = match.element if hasattr(element, "render") and not element.key: - element = cast(ComponentType, element) + element = cast(Component, element) element.key = key elif isinstance(element, dict) and not element.get("key", None): element = cast(VdomDict, element) - element["key"] = key + element["attributes"]["key"] = key return match @@ -118,10 +115,10 @@ def _match_route( location: Location, ) -> MatchedRoute | None: for resolver in compiled_routes: - match = resolver.resolve(location.pathname) + match = resolver.resolve(location.path) if match is not None: return _add_route_key(match, resolver.key) - _logger.debug("No matching route found for %s", location.pathname) + _logger.debug("No matching route found for %s", location.path) return None diff --git a/src/reactpy_router/types.py b/src/reactpy_router/types.py index 755e244..8e6f213 100644 --- a/src/reactpy_router/types.py +++ b/src/reactpy_router/types.py @@ -11,9 +11,8 @@ if TYPE_CHECKING: from collections.abc import Sequence - from reactpy.backend.types import Location from reactpy.core.component import Component - from reactpy.types import Key + from reactpy.types import Key, Location ConversionFunc: TypeAlias = Callable[[str], Any] """A function that converts a string to a specific type.""" @@ -42,7 +41,11 @@ class Route: def __hash__(self) -> int: el = self.element - key = el["key"] if is_vdom(el) and "key" in el else getattr(el, "key", id(el)) + key = ( + el["attributes"]["key"] + if is_vdom(el) and "attributes" in el and "key" in el["attributes"] + else getattr(el, "key", id(el)) + ) return hash((self.path, key, self.routes)) diff --git a/tests/test_router.py b/tests/test_router.py index ddef544..22574bd 100644 --- a/tests/test_router.py +++ b/tests/test_router.py @@ -20,7 +20,7 @@ def make_location_check(path, *routes): @component def check_location(): - assert use_location().pathname == path + assert use_location().path == path return html.h1({"id": name}, path) return route(path, check_location(), *routes)