Creating a Custom Hook to Handle Media Queries in React
This tutorial teaches you how to create a custom React hook for handling media queries.
Importing Dependencies
First, we need to import useState and useEffect from React.
import { useState, useEffect } from 'react';
Creating the useMediaQuery Hook
Next, we define our custom hook useMediaQuery.
export const useMediaQuery = (query: string) => {...};
Adding State
Inside our hook, we declare two state variables: isMobile and loadingIsMobile.
const [isMobile, setIsMobile] = useState(true);
const [loadingIsMobile, setLoadingIsMobile] = useState(false);
Adding an Effect
We then use the useEffect hook to add a side effect to our custom hook.
useEffect(() => {...}, []);
Handling Changes
Inside our effect, we first set loadingIsMobile to true. We then create a MediaQueryList object using the window.matchMedia method and our query parameter.
setLoadingIsMobile(true);
const matchQueryList = window.matchMedia(query);
const handleChange = (e: any) => {setIsMobile(e.matches);};
Setting up and Cleaning up the Listener
Still inside our effect, we set isMobile to the initial match status of our media query. We then add our handleChange function as a listener to our MediaQueryList object. We also set loadingIsMobile to false.
setIsMobile(matchQueryList.matches);
matchQueryList.addEventListener("change", handleChange);
setLoadingIsMobile(false);
return () => {matchQueryList.removeEventListener("change", handleChange);};
Returning the Result
Finally, our hook returns an object containing isMobile and loadingIsMobile.
return { isMobile, loadingIsMobile };
Complete Code
Here is the complete code of the custom hook useMediaQuery.
import { useState, useEffect } from 'react';
export const useMediaQuery = (query: string) => {
const [isMobile, setIsMobile] = useState(true);
const [loadingIsMobile, setLoadingIsMobile] = useState(false);
useEffect(() => {
setLoadingIsMobile(true);
const matchQueryList = window.matchMedia(query);
const handleChange = (e: any) => {
setIsMobile(e.matches);
};
setIsMobile(matchQueryList.matches);
matchQueryList.addEventListener('change', handleChange);
setLoadingIsMobile(false);
return () => {
matchQueryList.removeEventListener('change', handleChange);
};
}, []);
return { isMobile, loadingIsMobile };
};