Skip to content
Open
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
2 changes: 1 addition & 1 deletion docs/examples/python/use_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/python/use_search_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion docs/src/learn/routers-routes-and-links.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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/"
Expand Down
4 changes: 2 additions & 2 deletions src/js/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export interface ReactPyLocation {
pathname: string;
search: string;
path: string;
query_string: string;
}

export interface HistoryProps {
Expand Down
4 changes: 2 additions & 2 deletions src/js/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}

Expand Down
26 changes: 10 additions & 16 deletions src/reactpy_router/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"""

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/reactpy_router/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
13 changes: 5 additions & 8 deletions src/reactpy_router/routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"]
Expand Down Expand Up @@ -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


Expand All @@ -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
9 changes: 6 additions & 3 deletions src/reactpy_router/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down Expand Up @@ -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))


Expand Down
2 changes: 1 addition & 1 deletion tests/test_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down