Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suspense boundary broken (ignored) after second server action call #66431

Open
tilman opened this issue May 31, 2024 · 8 comments
Open

Suspense boundary broken (ignored) after second server action call #66431

tilman opened this issue May 31, 2024 · 8 comments
Labels
bug Issue was opened via the bug report template. Linking and Navigating Related to Next.js linking (e.g., <Link>) and navigation.

Comments

@tilman
Copy link

tilman commented May 31, 2024

Link to the code that reproduces this issue

https://github.com/trieb-work/nextjs-broken-suspense-bug-example

To Reproduce

  • start the app in dev mode using pnpm dev and open it in the browser
  • While this page loads you should see first 'page is loading...' from the loading.tsx
  • Then page.tsx returns from it's mocked api calls after 1s and is displaying 'Slept for 1000ms. Random digit X'
  • Then SlowServerComponent inside of a suspense in page.tsx returns from it's mocked api calls after 3s and is displaying 'Slept for 3000ms. Random digit X'
  • So far so good, everything of suspense logic works as expected so far
  • Now run the server action on the page via the button "run server action". The behavior should be the same as previously in (no loading.tsx is expected but suspense should work)
  • Now run the server action again and watch how "Slept for 1000ms. Random digit XX" and "Slept for 3000ms. Random digit XX" are displayed at the same time (after 4000ms, after both (1000ms + 3000ms) have returned).
  • The suspense is now "ignored". "Slept for 1000ms. Random digit XX" should show up before "Slept for 3000ms. Random digit XX" because of the suspense boundary.
  • But it seems like the suspense boundary get's ignored if the page is refreshed via an server action for the second time.
  • This bug results in bad user experience because long running API calls will block the whole page update and not only a small portion of the UI.
  • This behavior now persists for all upcoming form action calls until the page is hard reloaded via the browser navigation.

If starting the app in production mode (pnpm build + pnpm start) the same problem persists. Only difference will be that there is no loading page displayed first (due to static optimization). But this can also be disabled if page is opting out of static optimization.

Current vs. Expected behavior

Current:

  • after the second use of the form server action the suspense boundary is ignored and all server components are returned at once after the last server component has finished rendering.

Expected:

  • same behaviour as for initial render or for first server action call
  • in particular: the suspense should always behave the same

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 22.6.0: Wed Jul  5 22:22:05 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T6000
  Available memory (MB): 32768
  Available CPU cores: 10
Binaries:
  Node: 18.19.0
  npm: 10.2.3
  Yarn: 1.22.21
  pnpm: 8.6.0
Relevant Packages:
  next: 15.0.0-canary.3 // Latest available version is detected (15.0.0-canary.3).
  eslint-config-next: N/A
  react: 19.0.0-rc-6f23540c7d-20240528
  react-dom: 19.0.0-rc-6f23540c7d-20240528
  typescript: 5.3.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Navigation

Which stage(s) are affected? (Select all that apply)

next dev (local), next start (local), Vercel (Deployed)

Additional context

No response

@tilman tilman added the bug Issue was opened via the bug report template. label May 31, 2024
@github-actions github-actions bot added the Linking and Navigating Related to Next.js linking (e.g., <Link>) and navigation. label May 31, 2024
@kevinmitch14
Copy link
Contributor

I'm having similar issues.

  • loading.tsx is triggered on page load. (Expected)
  • If I invoke an action with revalidatePath("/") on /, loading.tsx is not triggered (expected?)
  • If I invoke an action with revalidatePath("/other-page") on /other-page, loading.tsx is triggered only on the first invocation, but not for subsequent invocations (not expected?)

This works as expected for me up to v14.2.0-canary.23, in v14.2.0-canary.24 I start to see issues.

@tilman
Copy link
Author

tilman commented Jun 3, 2024

@kevinmitch14 I think this is a different issue. My Problem is regarding Suspense boundaries and not regarding loading.tsx. I suggest you open a new issue or start a discussion on this topic.

@kevinmitch14
Copy link
Contributor

kevinmitch14 commented Jun 3, 2024

loading.tsx is a Suspense boundary.

https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming#instant-loading-states

When did the issues start to occur for you? Have you tried something before v14.2.0-canary.24?

@tilman
Copy link
Author

tilman commented Jun 7, 2024

Jep, I have tested and it was present in v14.2.4 as well

@tilman
Copy link
Author

tilman commented Jun 7, 2024

I have noticed it couple of month ago but never understood what is happening because of the hard way to reproduce it. But with the github example I linked above you can go back to older nextjs versions and reproduce it.

@tilman
Copy link
Author

tilman commented Jun 7, 2024

A temporal workaround is to add a key to the suspense boundary which changes on every render. But this feels kinda strange and I'm unsure about the negative consequences it has:

<Suspense key={Math.random()} fallback={...}>
   ...
<Suspense/>

@luke-concannon
Copy link

v15.0.0-canary.14 has fixed a similar issue I was having from 14.2.2.

@tilman
Copy link
Author

tilman commented Jun 10, 2024

Hey Luke, thanks for the hint. I have upgraded the example to 15.0.0-canary.23. Now the bug is even worse. Even on the first try it is not working now. In 15.0.0-canary.3 it was at least working for the first call of a server action and then the bug occured on all upcomming calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template. Linking and Navigating Related to Next.js linking (e.g., <Link>) and navigation.
Projects
None yet
Development

No branches or pull requests

3 participants