Skip to content

Conversation

@1WorldCapture
Copy link

@1WorldCapture 1WorldCapture commented Dec 22, 2025

This PR addresses two hydration mismatch errors encountered during development and debugging.

  1. Fix Root Layout Hydration Mismatch
    The ThemeScript component injects inline styles (CSS variables) into the tag at runtime to prevent FOUC (Flash of Unstyled Content). This caused a mismatch because the server-rendered tag did not contain these styles, while the client-side tag did immediately after hydration.

  2. Fix Editor Undo/Redo Buttons Hydration Mismatch
    The UndoRedoButtons component relies on useEditorStore which persists state to localStorage.

Server-side: Local storage is unavailable, so the undo/redo history is empty, rendering the buttons as disabled.
Client-side: The store hydrates from localStorage, restoring history and potentially rendering the buttons as enabled.
This difference caused a hydration error.

Summary by CodeRabbit

  • Bug Fixes
    • Improved undo/redo button reliability during component initialization
    • Resolved hydration warnings in the root layout

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

@vercel
Copy link

vercel bot commented Dec 22, 2025

@ChinaShrimp is attempting to deploy a commit to the tweakcn OSS program Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Dec 22, 2025

Walkthrough

This change adds hydration warning suppression to the root layout's HTML element and introduces a mounting state guard to the undo-redo buttons component via a React hook that prevents rendering until after client-side mount.

Changes

Cohort / File(s) Summary
Root Layout Configuration
app/layout.tsx
Added suppressHydrationWarning attribute to the HTML element
UndoRedo Component Safety
components/editor/action-bar/components/undo-redo-buttons.tsx
Added mounting guard via useState and useEffect hook; disabled states for both Undo and Redo buttons now require mounted to be true in addition to existing condition checks

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

  • The mounting guard in undo-redo-buttons follows a standard React hydration pattern but should be verified to ensure it doesn't affect UX or test expectations
  • Confirm the hydration warning suppression in layout.tsx is intentional and doesn't mask legitimate hydration issues

Possibly related PRs

Poem

🐰 A guard upon the mount so fine,
And warnings hushed in layouts divine,
With hooks and states, we bound with care,
No redo-ing 'til we're ready there!

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 clearly and concisely describes the main changes: resolving hydration issues in both the editor and root layout components, matching the actual modifications shown in the file summaries.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
components/editor/action-bar/components/undo-redo-buttons.tsx (1)

11-15: LGTM! Standard pattern for preventing hydration mismatches.

The mounted guard ensures both server and client render with mounted=false initially, preventing hydration errors from localStorage-based state. After mount, the component re-renders with the correct client-side state.

💡 Consider extracting to a reusable hook

Since the mounted guard pattern may be needed elsewhere, consider extracting it:

Create a new file hooks/use-mounted.ts:

import { useEffect, useState } from "react";

export function useMounted() {
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  return mounted;
}

Then use it in this component:

-  const [mounted, setMounted] = React.useState(false);
-
-  React.useEffect(() => {
-    setMounted(true);
-  }, []);
+  const mounted = useMounted();
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ce7e81 and 102fd5f.

📒 Files selected for processing (2)
  • app/layout.tsx
  • components/editor/action-bar/components/undo-redo-buttons.tsx
🔇 Additional comments (4)
components/editor/action-bar/components/undo-redo-buttons.tsx (3)

5-5: LGTM!

Import of React namespace is necessary for the useState and useEffect hooks used below.


7-7: Minor formatting adjustment.

The spacing change in the interface declaration doesn't affect functionality.


23-23: LGTM! Correctly prevents hydration mismatch.

Both buttons now check !mounted in addition to existing conditions. This ensures they render as disabled on both server and client initial render, then enable after mount based on actual localStorage state.

The UX will show a brief disabled state before enabling (if undo/redo history exists), which is expected and preferable to hydration errors.

Also applies to: 35-35

app/layout.tsx (1)

56-56: The dual suppressHydrationWarning attributes are redundant; consolidate to the script tag only.

The ThemeScript component already has suppressHydrationWarning on the <script> tag itself (line 100 in components/theme-script.tsx), which addresses the specific hydration mismatch caused by the inline script modifying CSS variables before React hydrates. The additional suppressHydrationWarning on the root <html> element (line 56) is unnecessarily broad and could mask other hydration issues.

Remove the suppression from the <html> tag and rely solely on the script tag's suppression, which targets the actual source of the mismatch. If you keep the root-level suppression, add a comment explaining why it's necessary beyond the script tag's own suppression.

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.

2 participants