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 }; };