I am trying to change the structure of my app using DOM media queries inside Next.js. Normal media queries (CSS) work no problem. In "pure" React, I could do something like this:
function HomePage () {
const [landscape, setLandscape] = useState(false)
useEffect(() => {
const landscapeHandler = e => {
console.log ("Change in landscape")
setLandscape({matches: e.matches});
}
window.matchMedia("((orientation:landscape)").addEventListener('change', landscapeHandler);
return () => {
window.removeEventListener('change', landscapeHandler);
}
}, [])
}
However, when using Next, changing the orientation of the screen doesn't do anything at all. Is there a workaround? I always thought useEffect is client-side only and therefore the right place to do such media queries... Many thanks in advance!
CodePudding user response:
Next.js executes the code first in the server and then in the client. So, when it executes in server, window would be undefined.
You can do it like the code below,
useEffect(() => {
if (typeof window !== "undefined") {
window.matchMedia("((orientation:landscape)").addEventListener('change', landscapeHandler);
}
// component Will Unmount
return () => {
if (typeof window !== "undefined") {
window.removeEventListener('change', landscapeHandler);
}
};
}, []);
CodePudding user response:
You could have used 'orientationchanged' listener, but I think it's depreciated.
You can try using the 'resize' listener.
useEffect(() => {
const handleChange = () => {
const width = document.documentElement.clientWidth
const height = document.documentElement.clientHeight
const orientation = width > height ? 'landscape' : 'portrait';
console.log('orientation: ', orientation, 'width', width, 'height', height)
}
if (typeof window !== 'undefined') {
const unsub = window.addEventListener('resize', handleChange)
return () => unsub();
}
},[])