Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 8 additions & 0 deletions e2e/ssr-hydration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ test('SSR community HTML hydrates SPA navigation and client search', async ({
page,
request,
}) => {
// A throw anywhere in the client runtime silently kills the rest of
// hydration, so the whole journey below is only meaningful if it stays
// error-free.
const clientErrors: Array<string> = []
page.on('pageerror', (error) => clientErrors.push(error.message))

await ensurePrimaryUserExists()
await seedCommunityListingInE2eDatabase({
...alphaListing,
Expand Down Expand Up @@ -205,4 +211,6 @@ test('SSR community HTML hydrates SPA navigation and client search', async ({
await expect(page).toHaveURL(/\/community$/)
await expect(page.getByText(betaListing.description)).toBeVisible()
await expect(page.getByRole('heading', { name: 'Not Found' })).toHaveCount(0)

expect(clientErrors).toEqual([])
})
7 changes: 6 additions & 1 deletion packages/worker/client/routes/community-detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,12 @@ export function CommunityDetailRoute(handle: Handle) {
shellLoadedForListingId = listingId
shellStatus = 'ready'
if (stargazersLoadedForListingId !== listingId) {
void loadStargazers(listingId)
// This runs during render, and `loadStargazers` calls
// `handle.update()` before its first await. The runtime only wires
// up a component's update scheduler after its first render
// returns, so calling it inline throws instead of scheduling:
// https://github.com/remix-run/remix/issues/11642
handle.queueTask(() => void loadStargazers(listingId))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Stale listing in deferred load

Medium Severity

Deferring loadStargazers with handle.queueTask captures listingId from the render that applied preloaded shell data. If the user navigates to another community before the task runs, the fetch can finish for the previous listing and update stargazer state while the UI shows a different package, unlike loadDetailShell which reads the current listing when its queued task executes.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 56f23fd. Configure here.

}
return true
}
Expand Down
Loading