Skip to content

Commit

Permalink
fix(react-router): make sure full matches are passed into route funct…
Browse files Browse the repository at this point in the history
…ions (#3039)
  • Loading branch information
schiller-manuel authored Dec 19, 2024
1 parent 253284a commit 347544c
Showing 1 changed file with 34 additions and 20 deletions.
54 changes: 34 additions & 20 deletions packages/react-router/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,16 @@ export class Router<

const matches: Array<AnyRouteMatch> = []

const getParentContext = (parentMatch?: AnyRouteMatch) => {
const parentMatchId = parentMatch?.id

const parentContext = !parentMatchId
? ((this.options.context as any) ?? {})
: (parentMatch.context ?? this.options.context ?? {})

return parentContext
}

matchedRoutes.forEach((route, index) => {
// Take each matched route and resolve + validate its search params
// This has to happen serially because each route's search params
Expand Down Expand Up @@ -1361,17 +1371,6 @@ export class Router<
}
}

const headFnContent = route.options.head?.({
matches,
match,
params: match.params,
loaderData: match.loaderData ?? undefined,
})

match.links = headFnContent?.links
match.scripts = headFnContent?.scripts
match.meta = headFnContent?.meta

// If it's already a success, update the headers
// These may get updated again if the match is refreshed
// due to being stale
Expand All @@ -1389,25 +1388,31 @@ export class Router<
// update the searchError if there is one
match.searchError = searchError

const parentMatchId = parentMatch?.id

const parentContext = !parentMatchId
? ((this.options.context as any) ?? {})
: (parentMatch.context ?? this.options.context ?? {})
const parentContext = getParentContext(parentMatch)

match.context = {
...parentContext,
...match.__routeContext,
...match.__beforeLoadContext,
}

matches.push(match)
})

matches.forEach((match, index) => {
const route = this.looseRoutesById[match.routeId]!
const existingMatch = this.getMatch(match.id)

// only execute `context` if we are not just building a location
if (!existingMatch && opts?._buildLocation !== true) {
const parentMatch = matches[index - 1]
const parentContext = getParentContext(parentMatch)

// Update the match's context
const contextFnContext: RouteContextOptions<any, any, any, any> = {
deps: loaderDeps,
deps: match.loaderDeps,
params: match.params,
context: match.context,
context: parentContext,
location: next,
navigate: (opts: any) =>
this.navigate({ ...opts, _fromLocation: next }),
Expand All @@ -1428,10 +1433,19 @@ export class Router<
}
}

matches.push(match)
const headFnContent = route.options.head?.({
matches,
match,
params: match.params,
loaderData: match.loaderData ?? undefined,
})

match.links = headFnContent?.links
match.scripts = headFnContent?.scripts
match.meta = headFnContent?.meta
})

return matches as any
return matches
}

getMatchedRoutes = (next: ParsedLocation, dest?: BuildNextOptions) => {
Expand Down

0 comments on commit 347544c

Please sign in to comment.