JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 25
  • Score
    100M100P100Q73382F
  • License MIT

Package Exports

  • react-responsiveness

Readme

React Responsiveness

Total Downloads Latest Release License Dependencies unpkg umd min:gzip size CircleCI PRs Welcome

Extremely light (~1 kB gzipped) plugin in terms of both size and runtime resource consumption.

I wanted something really easy to use, and as light as possible.
To be fair, I am a bit obsessed with both performance and ease of use. If curios, scroll down to "How it works".

Installation

yarn

yarn add react-responsiveness

npm

npm i react-responsiveness

Peer dependencies *

  • react@>=16.x
  • react-dom@>=16.x
  • jotai@>=1.x

* you need these deps in your project to use react-responsiveness

Demo

codesandbox.

Usage

The default breakpoints value is set to Bootstrap 5's responsiveness breakpoints preset:

A) Setup listeners:

import { useReactResponsiveness } from "react-responsiveness";

function App() {
    const { addListeners } = useReactResponsiveness();
    React.useLayoutEffect(() => {
        addListeners();
    }, []);
    // ...
}

Can be in any other component, but I recommend App as it's first to render. This only needs to be done once.

B) Use in any component:

import { useReactResponsiveness } from "react-responsiveness";

const { isMin, isMax, isOnly, currentInterval } = useReactResponsiveness()
    
return (<>
   <div>Current interval {currentInterval}</div>
   {isMin('sm') && (
       <!-- @media (min-width: 576px) -->
       <div>content...</div>
   )}
   {isMax('sm') && (
       <!-- @media (max-width: 767.9px) -->
       <div>content...</div>
   )}
   {isOnly('sm') && (
       <!-- @media (min-width: 576px) and (max-width: 767.9px) -->
       <div>content...</div>
   )}
</>)

Important notes

  • It is only required to call addListeners once per page/app. matches and currentInterval are shared state across all components using the hook.
  • The plugin uses jotai for sharing state across components (it's much like Recoil, except smaller). You need to install jotai in your project (~6 kB gzipped) to use react-responsiveness.

Using Breakpoint Library presets:

In App:

    const { addListeners } = useReactResponsiveness();
    React.useLayoutEffect(() => {
        addListeners(Presets.Tailwind_CSS);
    }, []);

All available presets:

Bootstrap_3, Bootstrap_4, Bootstrap_5, Bulma, Chakra, Foundation, Ionic, Material_Design, Materialize, Material_UI, Quasar, Semantic_UI, Skeleton, Tailwind_CSS, Windi_CSS

Notes:

  • If you maintain a CSS framework (or use one often) and want its preset added, open an issue or a PR.
  • If you spot any inconsistency in the presets (either my typo or some library update), please, let me know, I'll correct it.

Bespoke intervals:

In App:

    const { addListeners } = useReactResponsiveness();
    React.useLayoutEffect(() => {
        addListeners({
            small: 0,
            medium: 777,
            large: 1234
        });
    }, []);

... then, in any component, including App:

const { isOnly } = useReactResponsiveness()

return (<>
    {isOnly('medium') && (
        <!-- @media (min-width: 777px) and (max-width: 1233.9px) -->
        <div>content...</div>
    )}
</>)

How it works:

  • uses the native window.matchMedia(queryString) and only reacts to changes in the query's matches value. It's the same API powering CSS media queries
  • listeners are placed on the MediaQueryList instances, meaning they are garbage collected as soon as the app is unmounted, without leaving bound events behind on <body> or window object
  • no global pollution
  • only places listeners once and shares state across all components
  • in terms of memory and/or CPU consumption, listening to window.matchMadia 'change' events is a few hundred times lighter than using the "traditional" resize event listener method

Got issues?

Let me know!