Skip to content

fix(useWindowDimensions): guard window access for SSR / static prerender#1569

Merged
leecalcote merged 2 commits into
masterfrom
fix/window-dimensions-ssr-guard
May 21, 2026
Merged

fix(useWindowDimensions): guard window access for SSR / static prerender#1569
leecalcote merged 2 commits into
masterfrom
fix/window-dimensions-ssr-guard

Conversation

@hortison
Copy link
Copy Markdown
Contributor

Description

getWindowDimensions() reads window.innerWidth/innerHeight unguarded and is invoked eagerly via useState(getWindowDimensions()) on the initial render. Under server-side rendering or Next.js static-export prerender there is no window, so any component that calls useWindowDimensions() (e.g. a navbar) throws:

ReferenceError: window is not defined

during prerender. This blocked make ui-build (Next.js output: "export") in meshery-cloud, where NavBar calls useWindowDimensions() and renders during static export.

Fix

Return zeroed dimensions when window is undefined. The real values are read on the client during hydration (the useState initializer runs again client-side) and kept current by the existing resize listener. No behavior change in the browser.

Tests

Adds a node-environment regression test (src/__testing__/useWindowDimensions.test.tsx) asserting renderToString does not throw and falls back to 0x0 when window is absent, plus a positive case with window present.

  • npx jest src/__testing__/useWindowDimensions.test.tsx — 2 passed
  • npm run build — success (CJS/ESM/DTS)
  • pre-commit hook ran full suite — passed

Downstream

meshery-cloud consumes published sistent (^0.21.13) and has an interim consumer-side mitigation (wrapping NavBar in NoSsr). This PR is the root-cause fix; once released it can replace the need for SSR guards at every call site.

getWindowDimensions() read window.innerWidth/innerHeight unguarded and is
invoked eagerly via useState(getWindowDimensions()) on the initial render.
Under server-side rendering or Next.js static-export prerender there is no
window, so any component calling useWindowDimensions() (e.g. a navbar) threw
ReferenceError: window is not defined during prerender.

Return zeroed dimensions when window is undefined; the real values are read
on the client during hydration and updated by the existing resize listener.

Adds a node-environment regression test asserting renderToString does not
throw and falls back to 0x0 when window is absent.

Signed-off-by: miacycle <184569369+miacycle@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 21, 2026 19:25
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces SSR safety to the getWindowDimensions utility and adds a corresponding test suite to verify behavior in non-browser environments. A high-severity issue was identified regarding a hydration mismatch, as the initial client-side state will differ from the server-rendered output. The reviewer recommends initializing the state to zero and using an effect to capture actual dimensions after mounting to ensure hydration consistency and align the implementation with the provided documentation.

Comment thread src/custom/Helpers/Dimension/windowSize.tsx Outdated
Copy link
Copy Markdown
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

Fixes useWindowDimensions() so it can be safely used during SSR / Next.js static-export prerender without crashing the render pipeline, by guarding access to window and adding a regression test to prevent reintroducing the issue.

Changes:

  • Guarded getWindowDimensions() to return { width: 0, height: 0 } when window is unavailable (SSR/prerender).
  • Added a Jest node-environment SSR regression test using renderToString to assert no throw and verify the fallback behavior.

Reviewed changes

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

File Description
src/custom/Helpers/Dimension/windowSize.tsx Adds an SSR-safe window guard in getWindowDimensions() and updates the doc comment.
src/__testing__/useWindowDimensions.test.tsx Adds SSR regression coverage in a node Jest environment using react-dom/server.

Comment thread src/custom/Helpers/Dimension/windowSize.tsx Outdated
Comment thread src/custom/Helpers/Dimension/windowSize.tsx
Addresses review feedback: initializing state via useState(getWindowDimensions())
read window during render, which (a) diverged from the server's 0x0 render and
caused a hydration mismatch for SSR'd consumers, and (b) made the docstring's
'first effect-driven read' claim inaccurate (the effect only added a resize
listener, never an initial read).

Initialize state to 0x0 so the server render and first client (hydration)
render are identical, then sync to the real dimensions in the mount effect and
keep them current via the debounced resize listener. getWindowDimensions is now
only called on the client; its window guard remains as a defensive net.

Splits tests: SSR safety (node env, renderToString does not read window, falls
back to 0x0) and client behavior (jsdom renderHook: reads real dimensions on
mount, updates on debounced resize).

Signed-off-by: miacycle <184569369+miacycle@users.noreply.github.com>
@leecalcote leecalcote merged commit f5a856f into master May 21, 2026
5 checks passed
@leecalcote leecalcote deleted the fix/window-dimensions-ssr-guard branch May 21, 2026 21:39
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.

4 participants