Skip to content

fix(ssr): prevent hydration mismatches from client-only storage reads#392

Closed
Valyrian-Code wants to merge 1 commit into
fossology:mainfrom
Valyrian-Code:RAJVEER42/fix/header-hydration
Closed

fix(ssr): prevent hydration mismatches from client-only storage reads#392
Valyrian-Code wants to merge 1 commit into
fossology:mainfrom
Valyrian-Code:RAJVEER42/fix/header-hydration

Conversation

@Valyrian-Code

Copy link
Copy Markdown

Description

Fixes SSR hydration mismatches caused by browser storage being accessed during render. The server rendered fallback values (null/false), while the client immediately rendered values from storage, resulting in hydration warnings.

Changes

Header

  • isAuth() and getAllGroups() were previously called directly during render.
  • Replaced with authenticated and groups state variables, initialized to false and null.
  • Values are now populated in the existing useEffect, ensuring consistent server and client renders.

Footer

  • useState was initialized with getSessionStorage("fossologyVersion").
  • Moved the storage read into useEffect, preserving the existing cache behavior while avoiding hydration mismatches.

storageHelper

  • getLocalStorage and getSessionStorage could throw when attempting to parse "undefined" via JSON.parse.
  • Added guards for null and undefined values before parsing.

How to Test

  1. Start the development environment:

    docker compose -f docker-compose.dev.yml up
  2. Open:

    http://localhost:3000
    
  3. Open DevTools → Console.

  4. Verify that no hydration mismatch warnings or errors appear during page load.

Closes #243.

cc @deo002

Header called isAuth() and getAllGroups() directly in JSX render. Footer
initialized useState with getSessionStorage(). During SSR these return
null/false; on the client they return real values, causing React hydration
mismatches. Defer all storage reads to useEffect so server and client
render the same initial output.

Also guard getLocalStorage and getSessionStorage against stored
'undefined' strings, which caused JSON.parse to throw when a key was
set with an undefined value.

Signed-off-by: RAJVEER42 <irajveer.bishnoi2310@gmail.com>
Copilot AI review requested due to automatic review settings May 31, 2026 19:02
@github-actions github-actions Bot added the has merge conflicts PR has merge conflicts, require rebase label Jun 18, 2026
@github-actions

Copy link
Copy Markdown

This pull request has conflicts, please rebase to resolve those before we can evaluate the pull request.

@Valyrian-Code

Copy link
Copy Markdown
Author

Closing this PR — the issues it addressed are already fixed in the current main. The branch is ~25 commits behind, and during a rebase I confirmed:

  • src/shared/storageHelper.jsgetLocalStorage/getSessionStorage now guard against null/"undefined" values inside a try/catch.
  • src/components/Header/Header.jsx — auth state (isAuth/isAdmin/getUserName) is read in a useEffect and re-checked on route change, so no SSR/client mismatch.
  • src/components/Footer/Footer.jsxversion now initializes to useState(null) rather than reading session storage during render.

Rebasing would have reverted unrelated refactoring (cva variants, color tokens) on main, so closing as superseded. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

has merge conflicts PR has merge conflicts, require rebase

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The Footer has null and undefined values

1 participant