@@ -20,6 +20,8 @@ type Params<Key extends string = string> = {
2020 readonly [ key in Key ] : string | undefined ;
2121} ;
2222
23+ type UseRoutes = ( routes : RouteObject [ ] , locationArg ?: Partial < Location > | string ) => React . ReactElement | null ;
24+
2325// https://github.com/remix-run/react-router/blob/9fa54d643134cd75a0335581a75db8100ed42828/packages/react-router/lib/router.ts#L114-L134
2426interface RouteMatch < ParamKey extends string = string > {
2527 /**
@@ -141,6 +143,45 @@ function getNormalizedName(
141143 return [ location . pathname , 'url' ] ;
142144}
143145
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+
144185export function withSentryReactRouterV6Routing < P extends Record < string , any > , R extends React . FC < P > > ( Routes : R ) : R {
145186 if (
146187 ! _useEffect ||
@@ -169,39 +210,12 @@ export function withSentryReactRouterV6Routing<P extends Record<string, any>, R
169210 routes = _createRoutesFromChildren ( props . children ) ;
170211 isBaseLocation = true ;
171212
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 ) ;
178214 // eslint-disable-next-line react-hooks/exhaustive-deps
179215 } , [ props . children ] ) ;
180216
181217 _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 ) ;
205219 } , [ props . children , location , navigationType , isBaseLocation ] ) ;
206220
207221 isBaseLocation = false ;
@@ -217,3 +231,42 @@ export function withSentryReactRouterV6Routing<P extends Record<string, any>, R
217231 // will break advanced type inference done by react router params
218232 return SentryRoutes ;
219233}
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