useMedia
React sensor hook that tracks state of a CSS media query.
You can install use-media
with npm
npm install --save use-media
or with yarn
With useEffect
import useMedia from 'use-media'; // Alternatively, you can import as: // import {useMedia} from 'use-media'; const Demo = () => { // Accepts an object of features to test const isWide = useMedia({minWidth: '1000px'}); // Or a regular media query string const reduceMotion = useMedia('(prefers-reduced-motion: reduce)'); return ( <div> Screen is wide: {isWide ? '😃' : '😢'} </div> ); };
With useLayoutEffect
import {useMediaLayout} from 'use-media'; const Demo = () => { // Accepts an object of features to test const isWide = useMediaLayout({minWidth: '1000px'}); // Or a regular media query string const reduceMotion = useMediaLayout('(prefers-reduced-motion: reduce)'); return ( <div> Screen is wide: {isWide ? '😃' : '😢'} </div> ); };
Depending on your testing setup, you may need to mock window.matchMedia
on components that utilize the useMedia
hook. Below is an example of doing this in jest
:
/test-utilities/index.ts
import {mockMediaQueryList} from 'use-media/lib/useMedia'; // Types are also exported for convienence: // import {Effect, MediaQueryObject} from 'use-media/lib/types'; export interface MockMatchMedia { media: string; matches?: boolean; } function getMockImplementation({media, matches = false}: MockMatchMedia) { const mql: MediaQueryList = { ...mockMediaQueryList, media, matches, }; return () => mql; } export function jestMockMatchMedia({media, matches = false}: MockMatchMedia) { const mockedImplementation = getMockImplementation({media, matches}); window.matchMedia = jest.fn().mockImplementation(mockedImplementation); }
/components/MyComponent/MyComponent.test.tsx
const mediaQueries = { mobile: '(max-width: 767px)', prefersReducedMotion: '(prefers-reduced-motion: reduce)', }; describe('<MyComponent />', () => { const defaultProps: Props = { duration: 100, }; afterEach(() => { jestMockMatchMedia({ media: mediaQueries.prefersReducedMotion, matches: false, }); }); it('sets `duration` to `0` when user-agent `prefers-reduced-motion`', () => { jestMockMatchMedia({ media: mediaQueries.prefersReducedMotion, matches: true, }); const wrapper = mount(<MyComponent {...defaultProps} />); const child = wrapper.find(TransitionComponent); expect(child.prop('duration')).toBe(0); }); });
Depending on your app, you may be using the useMedia
hook to register many matchMedia
listeners across multiple components. It may help to elevate these listeners to Context
.
/components/MediaQueryProvider/MediaQueryProvider.tsx
import React, {createContext, useContext, useMemo} from 'react'; import useMedia from 'use-media'; interface Props { children: React.ReactNode; } export const MediaQueryContext = createContext(null); const mediaQueries = { mobile: '(max-width: 767px)', prefersReducedMotion: '(prefers-reduced-motion: reduce)', }; export default function MediaQueryProvider({children}: Props) { const mobileView = useMedia(mediaQueries.mobile); const prefersReducedMotion = useMedia(mediaQueries.prefersReducedMotion); const value = useMemo(() => ({mobileView, prefersReducedMotion}), [ mobileView, prefersReducedMotion, ]); return ( <MediaQueryContext.Provider value={value}> {children} </MediaQueryContext.Provider> ); } export function useMediaQueryContext() { return useContext(MediaQueryContext); }
/components/App/App.tsx
import React from 'react'; import MediaQueryProvider from '../MediaQueryProvider'; import MyComponent from '../MyComponent'; export default function App() { return ( <MediaQueryProvider> <div id="MyApp"> <MyComponent /> </div> </MediaQueryProvider> ); }
/components/MyComponent/MyComponent.tsx
import React from 'react'; import {useMediaQueryContext} from '../MediaQueryProvider'; export default function MyComponent() { const {mobileView, prefersReducedMotion} = useMediaQueryContext(); return ( <div> <p>mobileView: {Boolean(mobileView).toString()}</p> <p>prefersReducedMotion: {Boolean(prefersReducedMotion).toString()}</p> </div> ); }
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4