4
4
5
5
from dataclasses import replace
6
6
from logging import getLogger
7
- from typing import Any , Iterator , Literal , Sequence
7
+ from typing import Any , Iterator , Literal , Sequence , cast
8
8
9
9
from reactpy import component , use_memo , use_state
10
10
from reactpy .backend .hooks import ConnectionContext , use_connection
11
11
from 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
14
13
15
14
from reactpy_router .components import History
16
15
from reactpy_router .hooks import _route_state_context , _RouteState
@@ -86,6 +85,18 @@ def _iter_routes(routes: Sequence[RouteType]) -> Iterator[RouteType]:
86
85
yield parent
87
86
88
87
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
+
89
100
def _match_route (
90
101
compiled_routes : Sequence [CompiledRoute ],
91
102
location : Location ,
@@ -97,12 +108,14 @@ def _match_route(
97
108
match = resolver .resolve (location .pathname )
98
109
if match is not None :
99
110
if select == "first" :
100
- return [match ]
111
+ return [_add_route_key ( match , resolver . key ) ]
101
112
102
113
# Matching multiple routes is disabled since `react-router` no longer supports multiple
103
114
# matches via the `Route` component. However, it's kept here to support future changes
104
115
# 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
106
119
107
120
if not matches :
108
121
_logger .debug ("No matching route found for %s" , location .pathname )
0 commit comments