Is there a way to access device width or height in React or Next.js without using "window." or "document.". I understand we can get this with the hook useEffect and we don't have this error:
ReferenceError: window is not defined
but that's an overkill if I just need to access the width once
import { useEffect, useState } from "react";
const LayoutContainer = ({ Component, pageProps }) => {
const [mobile, setMobile] = useState(true);
useEffect(() => {
console.log(window.innerWidth < 450, window.innerWidth);
setMobile(window.innerWidth);
return () => setMobile(window.innerWidth < 450);
}, [window.innerWidth]); //ReferenceError: window is not defined
return (
<>
<Header />
<Component {...pageProps} />
<Footer mobile={mobile} />
</>
);
};
export default LayoutContainer;
CodePudding user response:
I suggest to you use this library: react-device-detect
import { useEffect, useState } from 'react';
import { isMobile } from 'react-device-detect';
const LayoutContainer = ({ Component, pageProps }) => {
return (
<>
<Header />
<Component {...pageProps} />
<Footer mobile={isMobile} />
</>
);
};
export default LayoutContainer;
CodePudding user response:
I would use window.matchMedia
but instead, add an event listener in the useEffect
and remove the window
dependency, like this:
const { useState, useEffect } = React;
const Example = () => {
const [isWide, setIsWide] = useState(null);
useEffect(() => {
const mql = window.matchMedia("(min-width: 768px)");
const onChange = () => setIsWide(!!mql.matches);
mql.addListener(onChange);
setIsWide(mql.matches);
return () => mql.removeListener(onChange);
}, []);
return <div>Is Wide: {isWide ? "true" : "false"}</div>;
};
ReactDOM.render(<Example />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Inspired by https://github.com/streamich/react-use/blob/master/src/useMedia.ts