Next.js Discord

Discord Forum

Suspense fires late

Answered
Spinge Bib Sqorpnts posted this in #help-forum
Open in Discord
Avatar
Hello! I have a Next.js application that uses suspense to wait for page load, but instead, when switching URLs it first shows the webpage, then shows and quickly hides the suspense fallback.

I'm unsure if I have a flawed knowledge of Suspense in Next or is some other part of my code screwing things up.
next info:
Operating System:        
  Platform: win32        
  Arch: x64
  Version: Windows 10 Pro
Binaries:
  Node: 18.17.1
  npm: N/A
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 13.5.3
  eslint-config-next: 13.5.3
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.2.2
Next.js Config:
  output: N/A


package.json
"dependencies": {
  "@emotion/cache": "^11.11.0",
  "@emotion/react": "^11.11.1",
  "@emotion/styled": "^11.11.0",
  "@mui/icons-material": "^5.14.9",
  "@mui/material": "^5.14.10",
  "@mui/x-date-pickers": "^6.14.0",
  "@next/bundle-analyzer": "^13.5.2",
  "dayjs": "^1.11.10",
  "lodash": "^4.17.21",
  "next": "13.5.4-canary.0",
  "next-intl": "3.0.0-beta.18",
  "overlayscrollbars": "^2.3.1",
  "overlayscrollbars-react": "^0.5.2",
  "react": "^18.2.0",
  "react-dom": "^18.2.0",
  "react-signature-canvas": "^1.0.6",
  "stylis": "^4.3.0",
  "stylis-plugin-rtl": "^2.1.1",
  "sweetalert2": "^11.7.28",
  "sweetalert2-react-content": "^5.0.7"
},
"devDependencies": {
  "@trivago/prettier-plugin-sort-imports": "^4.2.0",
  "@types/lodash": "^4.14.198",
  "@types/node": "^20.6.3",
  "@types/react": "18.2.22",
  "@types/react-dom": "18.2.7",
  "@types/react-signature-canvas": "^1.0.2",
  "@types/stylis": "^4.2.0",
  "@typescript-eslint/eslint-plugin": "^6.7.2",
  "@typescript-eslint/parser": "^6.7.2",
  "autoprefixer": "10.4.16",
  "eslint": "^8.49.0",
  "eslint-config-next": "13.5.3",
  "eslint-config-prettier": "^9.0.0",
  "eslint-plugin-prettier": "^5.0.0",
  "npm-check": "^6.0.1",
  "postcss": "^8.4.30",
  "prettier": "3.0.3",
  "sass": "^1.68.0",
  "tailwindcss": "3.3.3",
  "typescript": "5.2.2"
}
Answered by Spinge Bib Sqorpnts
@Alfonsus Ardani React.lazy() in some components further down the tree caused the double-trigger
View full answer

50 Replies

Avatar
I've already attempted using the Canary release, 13.5.4-canary.0, to no avail
Avatar
ure saying theres a slight delay/fkick where the fallback doesn't get rendered during suspense?
Avatar
When I go to a URL, it shows the 'full' webpage, flashes the fallback and then shows the webpage again
Avatar
does it happen on prod
also is this <Suspense> or loading.tsx?
Avatar
I tried both
It did, but i'll try again incase there was a one-off or just human error
Avatar
okay
seems like a weird routing issue, can you try reproducing it in a new project? using the latest canary version
Avatar
Sure, I'll try that. I'll also record a short video in-case we're not on the same page on what's happening
Still happens, not as noticable though
@Alfonsus Ardani
Image
(hid the top of the scren because of some sensitive info, but its just me typing in different urls)
Avatar
you know you are already tagging me when you reply xD no need to tag again
Avatar
oh sorry 😅
Didn't mean to double ping
Avatar
Now it doesn't show up, but I think that my code is flawed...
layout.tsx
const FetchData = async () => {
  const d = await fetch('https://restcountries.com/v3.1/all', { next: { revalidate: 0 } });
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(d.json());
    }, 3000);
  });
};

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  const d = await FetchData();
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  );
}
Avatar
uhhhh
it shouldnt show up if you havent made loading.tsx
Avatar
It exists
It's a simple spinner there so I didn't think I'd have to add it here
Avatar
i think the loading is only for child layout coponent
like the boundaries goes as follows

Layou -> Error -> Suspense -> Page

so if you make loading.tsx its only for child awaits like /page.tsx or /child/layout.tsx or /child/page.tsx
Avatar
That's right, but in the original project the layout is also on a child route
aka not the root layout
Avatar
hmm can i see the file structure for this new project
Avatar
Image
original project if relevant
Image
Avatar
i mean preferrably the await shouldn't be here but on the child layout/page instead
see if that worked
Avatar
it is, I moved it after you said I should try it on the child layout
Here its the app/[mof]/forms/161/layout.tsx
Avatar
also, in the OG project, after adding a timeout to the fetch request, something causes the loading.tsx to show up again and I have no idea what it is
is there any way to see what causes the loading.tsx to show up?
Avatar
its the async/await of server components.
Avatar
I wonder if it's nested lazy() loaded components...
Avatar
those causes the loading.tsx to show up
Avatar
the first time is okay, but what causes it to show up for the second time
Avatar
can you reproduce this effect in a new project?
im not sure either why it would get triggered twice
Avatar
ill try removing all lazy references in the OG
Avatar
@Alfonsus Ardani React.lazy() in some components further down the tree caused the double-trigger
Answer
Avatar
yeah
ive never used that
Avatar
That's fair
thank you for your help though :D
have a great day
Avatar
can you reproduce this? is this confirmed?
Avatar
well, removing lazy() in the OG project fixed the issue
Avatar
I'd like to add that using next/dynamic works, unlike React.lazy