Identifying device viewport using a custom react hook
Table of contents
No headings in the article.
There is a multitude of devices currently in use and identifying the device viewport helps in giving a user the best experience with our application. Hence having a custom hook to achieve makes a lot of sense and helps in quick development.
Technologies: React - Typescript
Detailed Steps:
- Start by defining all the media query breakpoints based on the device width.
/**
@description - Width of Tablet and Desktop
Anything less than Tablet Width will be for mobile
@filename - mediaQueries.ts
*/
const tabletWidth: number = 740;
const desktopWidth: number = 980;
const mediaQueries = {
desktop: `{min-width: ${desktopWidth}px}`,
mobile: `{max-width: ${tabletWidth - 1}px}`,
tablet: `{min-width: ${tabletWidth}px and {max-width: ${desktopWidth - 1}px}}`
};
The custom hook returns three different boolean values namely isMobile, isDesktop and isTablet.
MediaQueryList can be used for identifying and generating the values for the device. Compatibility is a major concern, although this should not be an issue with modern browsers.
// Modules
import { useState, useEffect } from "react";
// Utils
import { mediaQueries } from "./mediaQueries";
// Type Definitions
type ViewPortTypes = {
isDesktop: boolean;
isTablet: boolean;
isMobile: boolean;
}
// Default Values
const defaultSettings: ViewPortTypes = {
isDesktop: false,
isTablet: false,
isMobile: false
}
// Hook
const useViewPort = () => {
// Initialize
const [windowInfo, setWindowInfo] = useState<ViewPortTypes>(defaultSettings);
// Events
useEffect(() => {
const handleChange = () => {
setWindowInfo({
isDesktop: window.matchMedia(mediaQueries.desktop).matches,
isTablet: window.matchMedia(mediaQueries.tablet).matches,
isMobile: window.matchMedia(mediaQueries.mobile).matches,
})
};
// References for adding EventListeners for Window changes
const mediaQLDesktop = window.matchMedia(mediaQueries.desktop);
const mediaQLTablet = window.matchMedia(mediaQueries.tablet);
const mediaQLMobile = window.matchMedia(mediaQueries.mobile);
// Adding Listener (Browser should support addEventListener)
mediaQLDesktop.addEventListener("change", handleChange);
mediaQLTablet.addEventListener("change", handleChange);
mediaQLMobile.addEventListener("change", handleChange);
// Run on start
handleChange();
// useEffect cleanup
return () => {
mediaQLDesktop.removeEventListener("change", handleChange);
mediaQLTablet.removeEventListener("change", handleChange);
mediaQLMobile.removeEventListener("change", handleChange);
};
}, []);
return windowInfo;
};
export default useViewPort;
Please note: This custom hook can be used when the browser supports the events addEventListener and removeEventListener.
Check Browser support here for listeners
We can use the below checks to see if addEventListener and removeEventListener are supported. The deprecated statements are added for reference.
const addEventListenerSupported = !!mediaQLMobile.addEventListener;
// addListener (deprecated) statements
mediaQLDesktop.addListener(handleChange);
mediaQLTablet.addListener(handleChange);
mediaQLMobile.addListener(handleChange);
// removeListener (deprecated) statements
mediaQLDesktop.removeListener(handleChange);
mediaQLTablet.removeListener(handleChange);
mediaQLMobile.removeListener(handleChange);
This concludes the steps for writing a custom useViewPort hook. It will help in controlling the JSX elements which will be rendered on the screen.