Giter Site home page Giter Site logo

use-media's Introduction

use-media

useMedia React sensor hook that tracks state of a CSS media query.

Install

You can install use-media with npm

npm install --save use-media

or with yarn

yarn add use-media

Usage

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

Testing

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

Storing in Context

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

use-media's People

Contributors

ahmad-reza619 avatar beefchimi avatar bradwestfall avatar brianmitchl avatar dependabot[bot] avatar jacobrask avatar renovate-bot avatar semantic-release-bot avatar streamich avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.