Skip to content
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 47 additions & 32 deletions packages/router-core/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2463,35 +2463,45 @@ export class RouterCore<
let loaderIsRunningAsync = false
const route = this.looseRoutesById[routeId]!

const executeHead = async () => {
const executeHead = () => {
const match = this.getMatch(matchId)
// in case of a redirecting match during preload, the match does not exist
if (!match) {
return
}
if (
!route.options.head &&
!route.options.scripts &&
!route.options.headers
) {
return
}
const assetContext = {
matches,
match,
params: match.params,
loaderData: match.loaderData,
}
const headFnContent =
await route.options.head?.(assetContext)
const meta = headFnContent?.meta
const links = headFnContent?.links
const headScripts = headFnContent?.scripts
const styles = headFnContent?.styles

const scripts = await route.options.scripts?.(assetContext)
const headers = await route.options.headers?.(assetContext)
return {
meta,
links,
headScripts,
headers,
scripts,
styles,
}

return Promise.all([
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no await Promise.all()?
personally, i like async/await syntax more than "then".
unless there is a technical reason?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use await here, the function needs to be async, which means that it will always return a Promise, even if we returned early. I'd like to be able to do the if('then' in foo) thing where this function is called, but we can't do that if the function is async.

route.options.head?.(assetContext),
route.options.scripts?.(assetContext),
route.options.headers?.(assetContext),
]).then(([headFnContent, scripts, headers]) => {
const meta = headFnContent?.meta
const links = headFnContent?.links
const headScripts = headFnContent?.scripts
const styles = headFnContent?.styles

return {
meta,
links,
headScripts,
headers,
scripts,
styles,
}
})
}

const potentialPendingMinPromise = async () => {
Expand All @@ -2505,10 +2515,12 @@ export class RouterCore<
if (shouldSkipLoader(matchId)) {
if (this.isServer) {
const head = await executeHead()
updateMatch(matchId, (prev) => ({
...prev,
...head,
}))
if (head) {
updateMatch(matchId, (prev) => ({
...prev,
...head,
}))
}
return this.getMatch(matchId)!
}
}
Expand Down Expand Up @@ -2674,14 +2686,15 @@ export class RouterCore<
} catch (err) {
const head = await executeHead()

updateMatch(matchId, (prev) => {
prev._nonReactive.loaderPromise = undefined
return {
if (head) {
updateMatch(matchId, (prev) => ({
...prev,
...head,
}
})
handleRedirectAndNotFound(this.getMatch(matchId)!, err)
}))
}
const match = this.getMatch(matchId)!
match._nonReactive.loaderPromise = undefined
handleRedirectAndNotFound(match, err)
}
}

Expand Down Expand Up @@ -2717,10 +2730,12 @@ export class RouterCore<
// reason: parent's beforeLoad may have changed the route context
// and only now do we know the route context (and that the loader would not run)
const head = await executeHead()
updateMatch(matchId, (prev) => ({
...prev,
...head,
}))
if (head) {
updateMatch(matchId, (prev) => ({
...prev,
...head,
}))
}
}
}
if (!loaderIsRunningAsync) {
Expand Down
Loading