Facing while experimenting with device orientation
Here is the code, I am using
import React, { useState, useEffect } from 'react';
export default function App() {
const [isLandscape, setIsLandscape] = useState(window.innerWidth > window.innerHeight);
useEffect(() => {
function handleResize() {
setIsLandscape(window.innerWidth > window.innerHeight);
}
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<div>
{isLandscape ? <Landscape /> : <Portrait />}
</div>
);
}
And for your reference, here is the last and related question, I posted on SO
Calling functions as per device orientation
Experiment # 1
if (typeof window !== "undefined") {
const [isLandscape, setIsLandscape] = useState(window.innerWidth > window.innerHeight);
....
}
getting :
This resolved that issue, but showing the new one
Expected server HTML to contain a matching <div> in <body>.
Final code
export default function App() {
if (typeof window !== "undefined") {
const [isLandscape, setIsLandscape] = useState(window.innerWidth > window.innerHeight);
useEffect(() => {
function handleResize() {
setIsLandscape(window.innerWidth > window.innerHeight);
}
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<div>
{isLandscape ? <Landscape /> : <Portrait />}
</div>
);
}
}
Complete error says:
Error: Hydration failed because the initial UI does not match what was rendered on the server.
See more info here: https://nextjs.org/docs/messages/react-hydration-error
2
Answers
If you are using app router, add "use client" at the top to tell it it’s a client component so it has access to window.
The part of your code that is actually causing the issue is the
useState(window.innerWidth > window.innerHeight)
. That is run in both the server and the client and is what is giving you the "window is not defined" error.Your approach to wrapping everything in the
typeof window !== "undefined"
check doesn’t work because it does not return anything at all when run server side. It is theoretically possible to make that approach work by adding a return value when it is server-side, but there is a better solution:isLandscape
to allow for it to run server sideuseEffect
handler.useEffect
is only run client side so you can access window here without issue.By doing this, we’ve moved all the code that needs the window to client side code, and set appropriate defaults so the page can run server side while still returning a component as expected.