Skip to content

Conversation

@SoonIter
Copy link
Member

@SoonIter SoonIter commented Dec 25, 2025

Summary

  • Replace useLayoutEffect with useEffect in useStorageValue to avoid SSR warnings
  • Add SSR guard (typeof window check) in useStorageValue
  • Remove global renderCountForTocUpdate counter in PageTabs that causes hydration mismatch

Background

useStorageValue issues

The useStorageValue hook had two SSR compatibility issues:

  1. Used useLayoutEffect which causes warnings during SSR
  2. Accessed localStorage without checking if window is defined

PageTabs hydration mismatch

The PageTabs component used a global counter renderCountForTocUpdate that was incremented on every render. This counter was used to conditionally render a hidden <h2> element for TOC updates. Since the counter value could differ between server and client renders, this caused hydration mismatches.

Test plan

  • Verify no SSR warnings in console during build
  • Verify tabs with groupId work correctly (state persisted in localStorage)
  • Verify PageTabs component renders correctly without hydration errors

Copilot AI review requested due to automatic review settings December 25, 2025 19:01
@netlify
Copy link

netlify bot commented Dec 25, 2025

Deploy Preview for rspress-v2 ready!

Name Link
🔨 Latest commit 0104c1d
🔍 Latest deploy log https://app.netlify.com/projects/rspress-v2/deploys/694d8a8a5da6860008aa39f2
😎 Deploy Preview https://deploy-preview-2934--rspress-v2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves SSR (Server-Side Rendering) compatibility by fixing issues in the useStorageValue hook and PageTabs component. The changes address SSR warnings from useLayoutEffect usage, add browser environment guards, and eliminate a hydration mismatch caused by a global render counter.

Key changes:

  • Replace useLayoutEffect with useEffect and add SSR guard in useStorageValue hook
  • Remove global renderCountForTocUpdate counter and conditional TOC update logic from PageTabs component

Reviewed changes

Copilot reviewed 1 out of 1 changed files in this pull request and generated no comments.

File Description
packages/core/src/theme/logic/useStorageValue.ts Migrates from useLayoutEffect to useEffect with SSR guard for localStorage access, updates dependency array to include key
packages/core/src/theme/components/PageTabs/index.tsx Removes global counter and conditional hidden <h2> rendering that caused hydration mismatches
Comments suppressed due to low confidence (1)

packages/core/src/theme/logic/useStorageValue.ts:45

  • The setValue callback accesses localStorage and dispatchEvent without checking if window is defined. This will cause errors during SSR when this function is called. Add a guard to check typeof window !== 'undefined' before accessing browser APIs.
  const setValue = useCallback(
    (value: T) => {
      const next = value;
      if (next == null) {
        localStorage.removeItem(key);
      } else {
        localStorage.setItem(key, next.toString());
      }
      setValueInternal(next);
      dispatchEvent(
        // send custom event to communicate within same page
        // importantly this should not be a StorageEvent since those cannot
        // be constructed with a non-built-in storage area
        new CustomEvent<{ key: string; newValue: T }>(SYNC_STORAGE_EVENT_NAME, {
          detail: {
            key,
            newValue: next,
          },
        }),
      );
    },
    [key],
  );

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@SoonIter SoonIter force-pushed the fix/theme-ssr-compatibility branch from b23de65 to 0104c1d Compare December 25, 2025 19:03
@github-actions
Copy link
Contributor

github-actions bot commented Dec 25, 2025

Rsdoctor Bundle Diff Analysis

Found 3 projects in monorepo, 1 project with changes.

📊 Quick Summary
Project Total Size Change
node 9.3 MB 0
node_md 1.1 MB 0
web 15.1 MB +23.0 B (0.0%)
📋 Detailed Reports (Click to expand)

📁 web

Path: website/doc_build/diff-rsdoctor/web/rsdoctor-data.json

📌 Baseline Commit: c03d863a6b | PR: #2927

Metric Current Baseline Change
📊 Total Size 15.1 MB 15.1 MB +23.0 B (0.0%)
📄 JavaScript 14.4 MB 14.4 MB +23.0 B (0.0%)
🎨 CSS 115.4 KB 115.4 KB 0
🌐 HTML 0 B 0 B 0
📁 Other Assets 526.5 KB 526.5 KB 0

📦 Download Diff Report: web Bundle Diff

Generated by Rsdoctor GitHub Action

@SoonIter SoonIter merged commit 4a54e51 into main Dec 26, 2025
9 checks passed
@SoonIter SoonIter deleted the fix/theme-ssr-compatibility branch December 26, 2025 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants