Skip to content

Comments

clean: Add Suspense boundaries to prevent hydration errors#1215

Merged
elie222 merged 2 commits intomainfrom
fix/clean-page-suspense
Jan 6, 2026
Merged

clean: Add Suspense boundaries to prevent hydration errors#1215
elie222 merged 2 commits intomainfrom
fix/clean-page-suspense

Conversation

@elie222
Copy link
Owner

@elie222 elie222 commented Jan 6, 2026

User description

Fixes client-side exception errors on the /clean pages by adding Suspense boundaries around client components that use hooks.

  • Added Suspense with Loading component around ConfirmationStep in /clean/page.tsx
  • Updated /clean/onboarding/page.tsx to use Loading component instead of inline text
  • Added Suspense around CleanRun in /clean/run/page.tsx
  • Added Suspense around CleanHistory in /clean/history/page.tsx

Related to PR #1204 which fixed the same issue in the onboarding page.


Generated description

Below is a concise technical summary of the changes proposed in this PR:
Implement Suspense boundaries around client-side components such as ConfirmationStep, CleanRun, and CleanHistory on /clean pages to resolve client-side hydration errors. Utilize the Loading component as a fallback for these boundaries, ensuring a smoother user experience.

Latest Contributors(2)
UserCommitDate
elie222fix-resolve-React-hook...January 05, 2026
mojkakec12345@gmail.comfix-all-commentsJuly 11, 2025
This pull request is reviewed by Baz. Review like a pro on (Baz).

Summary by CodeRabbit

  • Improvements
    • Consistent loading indicators added across cleanup, onboarding, history, and run screens for smoother asynchronous loading and clearer visual feedback.
    • Rendering now defers appropriately while data loads, reducing UI flicker and improving perceived responsiveness.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Jan 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
inbox-zero Ready Ready Preview Jan 6, 2026 6:14pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 6, 2026

📝 Walkthrough

Walkthrough

Four clean-related pages now wrap their primary components in React Suspense boundaries using a shared Loading component as the fallback, replacing prior inline or missing loading UI and deferring render until suspense resolves.

Changes

Cohort / File(s) Summary
Clean pages — Suspense wrappers
apps/web/app/(app)/[emailAccountId]/clean/history/page.tsx, apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx, apps/web/app/(app)/[emailAccountId]/clean/page.tsx, apps/web/app/(app)/[emailAccountId]/clean/run/page.tsx
Imported Suspense and a shared Loading component; wrapped main components (CleanHistory, ConfirmationStep, CleanRun, etc.) in <Suspense fallback={<Loading />}>. Replaced hard-coded loading divs or added consistent fallback UI. No public API/signature changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested reviewers

  • baz-reviewer

Poem

🐇✨ I hop through code with nimble paws,
Wrapping renders in patient laws.
A Loading friend keeps waits polite—
Suspense now makes the pages right! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the pull request: adding Suspense boundaries to the clean pages to prevent hydration errors.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97443ca and 91062fa.

📒 Files selected for processing (1)
  • apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: test

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@macroscopeapp
Copy link
Contributor

macroscopeapp bot commented Jan 6, 2026

Add Suspense boundaries with Loading fallbacks to Clean pages to prevent hydration errors in page.tsx files

Introduce Suspense wrappers and replace string fallbacks with the Loading component around CleanHistory, ConfirmationStep, and CleanRun in Clean-related pages.

📍Where to Start

Start with the CleanPage Suspense wrapper around ConfirmationStep in page.tsx, then review similar patterns in history/page.tsx, onboarding/page.tsx, and run/page.tsx.


Macroscope summarized 91062fa.

Comment on lines +30 to 33
<Suspense fallback={<Loading />}>
<CleanHistory />
</Suspense>
</CardContent>
Copy link
Contributor

Choose a reason for hiding this comment

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

The new Suspense boundary on the history page cannot actually show the fallback because is a client component that only uses SWR's loading flags/LoadingContent and never throws a promise (no suspense: true, no use data). As written, the fallback is never rendered and the hydration mismatch the PR is meant to avoid is still unresolved, so the boundary is effectively a no-op.

Suggested change
<Suspense fallback={<Loading />}>
<CleanHistory />
</Suspense>
</CardContent>
<CleanHistory />
</CardContent>

Finding type: Logical Bugs

Copy link
Owner Author

Choose a reason for hiding this comment

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

You're right that CleanHistory doesn't throw a promise since SWR doesn't have suspense: true. However, the Suspense boundary is kept as a defensive measure - the original bug was a client-side exception during hydration on the /clean pages. The CleanHistory component uses useAccount() which internally uses useParams() and context, and wrapping in Suspense helps Next.js manage the hydration process for client components with hooks. It's a low-cost safeguard that aligns with the pattern in PR #1204.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks — that makes sense: keeping the Suspense boundary as a low-cost defensive measure for hydration issues (and consistent with PR #1204) is reasonable. Noted, and I’ll save this to memory once the PR is merged.

Comment on lines 97 to 101
return (
<div>
<Card className="my-4 max-w-2xl p-6 sm:mx-4 md:mx-auto">
<Suspense
key={step}
fallback={
<div className="flex h-[400px] items-center justify-center">
Loading...
</div>
}
>
<Suspense key={step} fallback={<Loading />}>
{renderStepContent()}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suspense now falls back to , but the previous placeholder had className="flex h-[400px] items-center justify-center" to reserve about 400px of vertical space. Replacing it with the minimal leaves the card body collapsing to the spinner height while each step loads, which contradicts the shared loading conventions in apps/web/CLAUDE.md and causes visible layout jank.

Suggested change
return (
<div>
<Card className="my-4 max-w-2xl p-6 sm:mx-4 md:mx-auto">
<Suspense
key={step}
fallback={
<div className="flex h-[400px] items-center justify-center">
Loading...
</div>
}
>
<Suspense key={step} fallback={<Loading />}>
{renderStepContent()}
return (
<div>
<Card className="my-4 max-w-2xl p-6 sm:mx-4 md:mx-auto">
<Suspense key={step} fallback={<div className="flex h-[400px] items-center justify-center"><Loading /></div>}>
{renderStepContent()}

Finding type: Logical Bugs

Copy link
Owner Author

Choose a reason for hiding this comment

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

Good catch! Restored the 400px height container around the Loading component to prevent layout jank. Fixed in 91062fa.

Copy link
Contributor

Choose a reason for hiding this comment

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

Commit 91062fa addressed this comment. The Suspense fallback was updated to wrap the <Loading /> component in a div with className="flex h-[400px] items-center justify-center", which reserves the 400px vertical space and prevents layout jank during loading, exactly as suggested in the comment.

@elie222 elie222 merged commit 91062fa into main Jan 6, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant