-
Notifications
You must be signed in to change notification settings - Fork 0
Fix: Improve useIsMobile SSR and initial render consistency
#126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThe Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~5 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/hooks/use-mobile.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/hooks/use-mobile.ts (1)
src/lib/responsive.ts (1)
MOBILE_BREAKPOINT(1-1)
| const [isMobile, setIsMobile] = React.useState<boolean>(() => { | ||
| if (typeof window === 'undefined') { | ||
| return false; // Default for SSR | ||
| } | ||
| return window.innerWidth < MOBILE_BREAKPOINT; // Initial value for client | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n src/hooks/use-mobile.tsRepository: Authormaton/authormaton
Length of output: 1049
🏁 Script executed:
rg -n "useIsMobile" --type=ts --type=tsx -C3Repository: Authormaton/authormaton
Length of output: 94
🏁 Script executed:
rg -n "useIsMobile" --type=ts -C3Repository: Authormaton/authormaton
Length of output: 6544
🏁 Script executed:
rg -n "useIsMobile" -C3Repository: Authormaton/authormaton
Length of output: 6544
🏁 Script executed:
sed -n '55,80p' src/components/ui/sidebar.tsxRepository: Authormaton/authormaton
Length of output: 958
🏁 Script executed:
sed -n '14,40p' src/components/models/projects/ProjectsTable.tsxRepository: Authormaton/authormaton
Length of output: 908
🏁 Script executed:
sed -n '8,30p' src/components/layouts/GeneralLayout.tsxRepository: Authormaton/authormaton
Length of output: 913
🏁 Script executed:
sed -n '14,60p' src/components/models/projects/ProjectsTable.tsxRepository: Authormaton/authormaton
Length of output: 1433
🏁 Script executed:
rg -n "suppressHydrationWarning" --type=tsRepository: Authormaton/authormaton
Length of output: 143
🏁 Script executed:
rg -n "suppressHydrationWarning"Repository: Authormaton/authormaton
Length of output: 143
Hydration mismatch from lazy useState initializer reading window
The lazy initializer with typeof window === 'undefined' is runtime-safe for SSR, but it causes server and initial client renders to diverge:
- On the server,
isMobileis alwaysfalse. - On the client during hydration, the initializer may return
trueifinnerWidth < 768.
This causes hydration mismatches in components that conditionally render based on isMobile:
- GeneralLayout.tsx renders
<Sheet>on mobile but<div>on desktop based on this value - ProjectsTable.tsx renders a grid on mobile but
<BasicTable>on desktop based on this value
Both components will render different markup on the server versus the client, triggering hydration warnings and potential layout shifts after the effect updates.
Initialize to a constant value (e.g., useState(false)) and rely on the effect to update after mount, ensuring server and first hydration render are consistent. Alternatively, make these components client-only or add suppressHydrationWarning if the brief mismatch is acceptable.
🤖 Prompt for AI Agents
In src/hooks/use-mobile.ts around lines 6 to 11, the lazy useState initializer
reads window causing server vs initial client render divergence; change the
initial state to a constant (e.g., useState(false)) so SSR and first hydration
produce the same output, then in a useEffect run only on mount to read
window.innerWidth and setIsMobile accordingly, and also add a resize listener
inside that effect to update on viewport changes with proper cleanup on unmount.
Overview: This PR updates the
useIsMobilehook to ensure consistent behavior during server-side rendering (SSR) and on initial client-side renders.Changes
useStateinitialization insrc/hooks/use-mobile.tsto check forwindowavailability. Ifwindowisundefined(SSR), it defaults tofalse. Otherwise, it directly calculates the initialisMobilestate based onwindow.innerWidth.checkIsMobile()call in theuseEffecthook, as the initial state is now correctly set duringuseStateinitialization.Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.