Custom Hooks for detecting window size in React
Author : JaNakh Pon , December 29, 2021
Tags
Intro
Just like hiding, displaying contents based on sizes in css, we might also want to display different Components based on screen sizes in React.
In this article, we are going to write custom hooks to detect screen sizes using window.matchMedia
and window.innerWidth
.
Basic Media Queries
Media queries are useful when you want to modify your site or app depending on a device's general type (such as print vs. screen) or specific characteristics and parameters (such as screen resolution or browser viewport width).
We can use max-
(up to) and min-
(>) functionalities to target a specific window size.
For example:
/* Targeting UP TO screen sizes with max-width */
@media (max-width: 979px) {
/* Selectors and styles affecting screens UP TO 979px (Desktop) */
}
@media (max-width: 767px) {
/* Selectors and styles affecting screens UP TO 767px (Tablet) */
}
@media (max-width: 480px) {
/* Selectors and styles affecting screens UP TO 480px (Phone) */
}
/* Targeting > screen sizes with min-width */
@media (min-width: 767px) {
/* Selectors and styles affecting screens WIDER THAN 767px (Tablet) */
}
@media (min-width: 979px) {
/* Selectors and styles affecting screens WIDER THAN 979px (Desktop) */
}
@media (min-width: 1200px) {
/* Selectors and styles affecting screens WIDER THAN 1200px (Large Desktop) */
}
/*Orientation*/
@media only screen and (orientation: portrait) {
}
@media only screen and (orientation: landscape) {
}
@media (min-width: 768px) and (max-width: 1024px) and (orientation: landscape) {
}
window.matchMedia
The Window interface's matchMedia() method returns a new MediaQueryList object that can then be used to determine if the document matches the media query string, as well as to monitor the document to detect when it matches (or stops matching) that media query.
Let's write a custom hook using window.matchMedia targeting screen size (>)larger than 960px.
import { useState, useEffect } from "react";
function useMedia() {
const [isDesktopSize, setIsDesktopSize] = useState<boolean>(false);
useEffect(() => {
const media = window.matchMedia("(min-width: 960px)");
const listener = () => setIsDesktopSize(media.matches);
listener();
window.addEventListener("resize", listener);
return () => window.removeEventListener("resize", listener);
}, [isDesktopSize]);
return { isDesktopSize };
}
export default useMedia;
We might need to use useMedia
to display different contents based on screen sizes:
import useMedia from "../hooks/useMedia";
const MainContent = () => {
const { isDesktopSize } = useMedia();
return isDesktopSize ? (
<h1>Desktop (window.matchMedia)</h1>
) : (
<h1>Tablet & Mobile (window.matchMedia)</h1>
);
};
export default MainContent;
window.innerWidth returns the interior width of the window in pixels. This includes the width of the vertical scroll bar, if one is present. window.innerWidth
More precisely, innerWidth returns the width of the window's layout viewport. The interior height of the window—the height of the layout viewport—can be obtained from the innerHeight property.
Let's write a custom hook using window.innerWidth targeting screen size (>)larger than 960px.
import { useState, useEffect } from "react";
function useWidth() {
const [isDesktopWidthSize, setIsDesktopWidthSize] = useState<boolean>(false);
useEffect(() => {
const listener = () => setIsDesktopWidthSize(window.innerWidth > 960);
listener();
window.addEventListener("resize", listener);
return () => window.removeEventListener("resize", listener);
}, [isDesktopWidthSize]);
return { isDesktopWidthSize };
}
export default useWidth;
Let's use useWidth hook
like we did with useMedia hook
previously:
import useMedia from "../hooks/useMedia";
import useWidth from "../hooks/useWidth";
const MainContent = () => {
const { isDesktopSize } = useMedia();
const { isDesktopWidthSize } = useWidth();
return (
<>
{isDesktopSize ? (
<h1>Desktop (window.matchMedia)</h1>
) : (
<h1>Tablet & Mobile (window.matchMedia)</h1>
)}
<hr />
{isDesktopWidthSize ? (
<h1>Desktop (window.innerWidth)</h1>
) : (
<h1>Tablet & Mobile (window.innerWidth)</h1>
)}
</>
);
};
export default MainContent;
Now, we have two custom hooks that we can use to detect screen sizes in our future React projects!.
Ref => Using media queries
Ref => Window.matchMedia()
Ref => Window.innerWidth
Ref => Why you should use window.matchMedia when checking for window resizes in Javascript