44
55from dataclasses import replace
66from logging import getLogger
7- from typing import Any , Iterator , Literal , Sequence
7+ from typing import Any , Iterator , Literal , Sequence , cast
88
99from reactpy import component , use_memo , use_state
1010from reactpy .backend .hooks import ConnectionContext , use_connection
1111from reactpy .backend .types import Connection , Location
12- from reactpy .core .types import VdomDict
13- from reactpy .types import ComponentType
12+ from reactpy .types import ComponentType , VdomDict
1413
1514from reactpy_router .components import History
1615from reactpy_router .hooks import _route_state_context , _RouteState
@@ -86,6 +85,18 @@ def _iter_routes(routes: Sequence[RouteType]) -> Iterator[RouteType]:
8685 yield parent
8786
8887
88+ def _add_route_key (match : tuple [Any , dict [str , Any ]], key : str | int ) -> Any :
89+ """Add a key to the VDOM or component on the current route, if it doesn't already have one."""
90+ element , _params = match
91+ if hasattr (element , "render" ) and not element .key :
92+ element = cast (ComponentType , element )
93+ element .key = key
94+ elif isinstance (element , dict ) and not element .get ("key" , None ):
95+ element = cast (VdomDict , element )
96+ element ["key" ] = key
97+ return match
98+
99+
89100def _match_route (
90101 compiled_routes : Sequence [CompiledRoute ],
91102 location : Location ,
@@ -97,12 +108,14 @@ def _match_route(
97108 match = resolver .resolve (location .pathname )
98109 if match is not None :
99110 if select == "first" :
100- return [match ]
111+ return [_add_route_key ( match , resolver . key ) ]
101112
102113 # Matching multiple routes is disabled since `react-router` no longer supports multiple
103114 # matches via the `Route` component. However, it's kept here to support future changes
104115 # or third-party routers.
105- matches .append (match ) # pragma: no cover
116+ # TODO: The `resolver.key` value has edge cases where it is not unique enough to use as
117+ # a key here, unless we begin throwing errors for duplicate routes.
118+ matches .append (_add_route_key (match , resolver .key )) # pragma: no cover
106119
107120 if not matches :
108121 _logger .debug ("No matching route found for %s" , location .pathname )
0 commit comments