@@ -20,6 +20,8 @@ type Params<Key extends string = string> = {
20
20
readonly [ key in Key ] : string | undefined ;
21
21
} ;
22
22
23
+ type UseRoutes = ( routes : RouteObject [ ] , locationArg ?: Partial < Location > | string ) => React . ReactElement | null ;
24
+
23
25
// https://github.com/remix-run/react-router/blob/9fa54d643134cd75a0335581a75db8100ed42828/packages/react-router/lib/router.ts#L114-L134
24
26
interface RouteMatch < ParamKey extends string = string > {
25
27
/**
@@ -141,6 +143,45 @@ function getNormalizedName(
141
143
return [ location . pathname , 'url' ] ;
142
144
}
143
145
146
+ function updatePageloadTransaction ( location : Location , routes : RouteObject [ ] ) : void {
147
+ if ( activeTransaction ) {
148
+ const [ name , source ] = getNormalizedName ( routes , location , _matchRoutes ) ;
149
+ activeTransaction . setName ( name ) ;
150
+ activeTransaction . setMetadata ( { source } ) ;
151
+ }
152
+ }
153
+
154
+ function handleNavigation (
155
+ location : Location ,
156
+ routes : RouteObject [ ] ,
157
+ navigationType : Action ,
158
+ isBaseLocation : boolean ,
159
+ ) : void {
160
+ if ( isBaseLocation ) {
161
+ if ( activeTransaction ) {
162
+ activeTransaction . finish ( ) ;
163
+ }
164
+
165
+ return ;
166
+ }
167
+
168
+ if ( _startTransactionOnLocationChange && ( navigationType === 'PUSH' || navigationType === 'POP' ) ) {
169
+ if ( activeTransaction ) {
170
+ activeTransaction . finish ( ) ;
171
+ }
172
+
173
+ const [ name , source ] = getNormalizedName ( routes , location , _matchRoutes ) ;
174
+ activeTransaction = _customStartTransaction ( {
175
+ name,
176
+ op : 'navigation' ,
177
+ tags : SENTRY_TAGS ,
178
+ metadata : {
179
+ source,
180
+ } ,
181
+ } ) ;
182
+ }
183
+ }
184
+
144
185
export function withSentryReactRouterV6Routing < P extends Record < string , any > , R extends React . FC < P > > ( Routes : R ) : R {
145
186
if (
146
187
! _useEffect ||
@@ -169,39 +210,12 @@ export function withSentryReactRouterV6Routing<P extends Record<string, any>, R
169
210
routes = _createRoutesFromChildren ( props . children ) ;
170
211
isBaseLocation = true ;
171
212
172
- if ( activeTransaction ) {
173
- const [ name , source ] = getNormalizedName ( routes , location , _matchRoutes ) ;
174
- activeTransaction . setName ( name ) ;
175
- activeTransaction . setMetadata ( { source } ) ;
176
- }
177
-
213
+ updatePageloadTransaction ( location , routes ) ;
178
214
// eslint-disable-next-line react-hooks/exhaustive-deps
179
215
} , [ props . children ] ) ;
180
216
181
217
_useEffect ( ( ) => {
182
- if ( isBaseLocation ) {
183
- if ( activeTransaction ) {
184
- activeTransaction . finish ( ) ;
185
- }
186
-
187
- return ;
188
- }
189
-
190
- if ( _startTransactionOnLocationChange && ( navigationType === 'PUSH' || navigationType === 'POP' ) ) {
191
- if ( activeTransaction ) {
192
- activeTransaction . finish ( ) ;
193
- }
194
-
195
- const [ name , source ] = getNormalizedName ( routes , location , _matchRoutes ) ;
196
- activeTransaction = _customStartTransaction ( {
197
- name,
198
- op : 'navigation' ,
199
- tags : SENTRY_TAGS ,
200
- metadata : {
201
- source,
202
- } ,
203
- } ) ;
204
- }
218
+ handleNavigation ( location , routes , navigationType , isBaseLocation ) ;
205
219
} , [ props . children , location , navigationType , isBaseLocation ] ) ;
206
220
207
221
isBaseLocation = false ;
@@ -217,3 +231,42 @@ export function withSentryReactRouterV6Routing<P extends Record<string, any>, R
217
231
// will break advanced type inference done by react router params
218
232
return SentryRoutes ;
219
233
}
234
+
235
+ export function wrapUseRoutes ( origUseRoutes : UseRoutes ) : UseRoutes {
236
+ if ( ! _useEffect || ! _useLocation || ! _useNavigationType || ! _matchRoutes || ! _customStartTransaction ) {
237
+ __DEBUG_BUILD__ &&
238
+ logger . warn (
239
+ 'reactRouterV6Instrumentation was unable to wrap `useRoutes` because of one or more missing parameters.' ,
240
+ ) ;
241
+
242
+ return origUseRoutes ;
243
+ }
244
+
245
+ let isBaseLocation : boolean = false ;
246
+
247
+ return ( routes : RouteObject [ ] , location ?: Partial < Location > | string ) : React . ReactElement | null => {
248
+ const SentryRoutes : React . FC < unknown > = ( props : unknown ) => {
249
+ const Routes = origUseRoutes ( routes , location ) ;
250
+
251
+ const locationArgObject = typeof location === 'string' ? { pathname : location } : location ;
252
+ const locationObject = ( locationArgObject as Location ) || _useLocation ( ) ;
253
+ const navigationType = _useNavigationType ( ) ;
254
+
255
+ _useEffect ( ( ) => {
256
+ isBaseLocation = true ;
257
+
258
+ updatePageloadTransaction ( locationObject , routes ) ;
259
+ } , [ props ] ) ;
260
+
261
+ _useEffect ( ( ) => {
262
+ handleNavigation ( locationObject , routes , navigationType , isBaseLocation ) ;
263
+ } , [ props , locationObject , navigationType , isBaseLocation ] ) ;
264
+
265
+ isBaseLocation = false ;
266
+
267
+ return Routes ;
268
+ } ;
269
+
270
+ return < SentryRoutes /> ;
271
+ } ;
272
+ }
0 commit comments