-
Notifications
You must be signed in to change notification settings - Fork 61
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
fix(web): MobileAppBanner hydration error fix suggestion #17671
Conversation
WalkthroughThe pull request modifies the Changes
Possibly related PRs
Suggested Labels
Suggested Reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
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: 0
🔭 Outside diff range comments (1)
apps/web/components/MobileAppBanner/MobileAppBanner.tsx (1)
Line range hint
34-45
: Improve platform detection to prevent potential hydration issues.The
getMobilePlatform
function directly accesses browser APIs which could cause issues during server-side rendering. While the function checks fortypeof navigator
, it's better to encapsulate all browser-specific logic.Consider this improved implementation:
- const getMobilePlatform = (): string => { - if (typeof navigator === 'undefined') { - return '' - } - const userAgent = navigator.userAgent || navigator.vendor - return /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream - ? 'apple' - : 'android' - } + const getMobilePlatform = (): string => { + if (typeof window === 'undefined') { + return '' + } + try { + const userAgent = window.navigator.userAgent || window.navigator.vendor + return /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream + ? 'apple' + : 'android' + } catch { + return '' + } + }
🧹 Nitpick comments (3)
apps/web/components/MobileAppBanner/MobileAppBanner.tsx (3)
59-60
: The hydration fix looks promising but could be further improved.The change to include
!isMounted
in the Hidden component's screen prop helps prevent hydration mismatches by ensuring consistent server/client rendering. However, we could further optimize this to prevent any potential flash of content.Consider this alternative approach:
- return ( - <Hidden screen={hidden || !isMounted} print={true}> + return ( + <> + {/* Prevent hydration mismatch by deferring client-side rendering */} + {typeof window !== 'undefined' && ( + <Hidden screen={hidden} print={true}>This approach ensures the banner is only rendered client-side, completely eliminating the possibility of hydration mismatches.
Line range hint
15-19
: Enhance type safety for browser APIs.The current type declarations could be more specific to prevent potential type-related issues.
Consider these type improvements:
declare global { interface Window { - MSStream: unknown + MSStream: boolean | undefined + navigator: Navigator & { + vendor: string + } } }
Line range hint
27-33
: Optimize state management and initialization.The component uses multiple state variables that could be consolidated, and the initialization logic could be improved.
Consider these improvements:
- const [isMounted, setIsMounted] = useState(false) - const [hidden, setHidden] = useState<boolean>( - !!Cookies.get(COOKIE_NAME) || !appleLink || !androidLink, - ) - const [isApple, setIsApple] = useState<boolean>(false) + interface BannerState { + isMounted: boolean; + hidden: boolean; + platform: 'apple' | 'android' | ''; + } + + const [bannerState, setBannerState] = useState<BannerState>(() => ({ + isMounted: false, + hidden: !!Cookies.get(COOKIE_NAME) || !appleLink || !androidLink, + platform: '', + }));This approach:
- Consolidates related state
- Uses a single state update
- Makes the state structure more maintainable
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/components/MobileAppBanner/MobileAppBanner.tsx
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
apps/web/components/MobileAppBanner/MobileAppBanner.tsx (1)
Pattern apps/**/*
: "Confirm that the code adheres to the following:
- NextJS best practices, including file structure, API routes, and static generation methods.
- Efficient state management and server-side rendering techniques.
- Optimal use of TypeScript for component and utility type safety."
* fix: init * fix: more fix --------- Co-authored-by: Jón Levy <[email protected]>
What
local run on main branch
![image](https://private-user-images.githubusercontent.com/9449413/406937144-2c8e2a41-7465-4784-a3d9-87d1c280860e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzg3ODU2MDAsIm5iZiI6MTczODc4NTMwMCwicGF0aCI6Ii85NDQ5NDEzLzQwNjkzNzE0NC0yYzhlMmE0MS03NDY1LTQ3ODQtYTNkOS04N2QxYzI4MDg2MGUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIwNSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMDVUMTk1NTAwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9OGMwODk2YzIzYjlmMjM5ZjIxNjRhYzBiY2MxYjYwOGY1OTI4MmUyZjAwZjBmYzcwYjk0NTVhMjMzOTgxYjRkMCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.SdgkJ_-u9kWugKLmwh1BDvpZ7zCObbFxXBjxxySb--I)
after pr changes
![image](https://private-user-images.githubusercontent.com/9449413/406937601-6ab9d2ae-4e44-4092-88f6-604f826f286a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzg3ODU2MDAsIm5iZiI6MTczODc4NTMwMCwicGF0aCI6Ii85NDQ5NDEzLzQwNjkzNzYwMS02YWI5ZDJhZS00ZTQ0LTQwOTItODhmNi02MDRmODI2ZjI4NmEucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIwNSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMDVUMTk1NTAwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YjY4MTQ3NTk3MTFhNTMyNmMxYTkyY2EyNmJhZmY2Njg3YTQ4Mzg1MGU4ZjBmYTBlZDkyNGNiMTRjYTIxM2UxZiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.Qn8hv0fxbtfW9Ug6Kf-naVvuu_Y3Fa3YFKSe2NM5UIw)
Still some issues but the hydration error is (mostly) gone
Checklist:
Summary by CodeRabbit