@herbco/react-media-match
TypeScript icon, indicating that this package has built-in type declarations

1.4.2 • Public • Published

react-media-match

Build Status coverage-badge NPM version

Mobile first react responsive framework made easy.

  • 🐍 "mobile-first", "gap-less", and bug-less rendering.
    • In all the cases one rendering branch will be picked, and only one!
    • Never forget to render something, never render two branches simultaneously.
  • 💻 SSR friendly. Customize the target rendering mode, and SSR for any device.
  • 💡 Provides Media Matchers and Media Pickers. Render different components based on media, or calculate strings.
  • 🧠 written in TypeScript

Usage

npm install react-media-match

yarn add react-media-match

Just:

  1. Define once all your media queries (2-3-4 usual), and then use them simultaneously!
  2. Define how application should look like on all resolutions.

Each Media Query is responsible only for a single "dimension" - width, height or orientation.

  • If you have defined what Query should render on mobile, but not everything else - it will always use mobile.
  • defined mobile and desktop, but not tablet or laptop? It will use "value to the left".

"Pick value to the left" is the core concept. It protects you from mistakes, and allows to skip intermediate resolutions, if they should inherit styles from "lesser" query.

  • If you need to respond to screen size and orientation - create 2 separate matchers, and work with them - separately!
  • If you need to respond to NOT screen or NOT media - just provide values MediaMatcher should match against and that's done!

react-media-match was made with maintainability and mobile first approach in mind. It makes things simpler.

react-media-match provides two components and one function, and none of them awaits query as a prop,

import { MediaMatcher, ProvideMediaMatchers } from "react-media-match";

<ProvideMediaMatchers> // this component will calculate all Media's and put data into the React Context
    <MediaMatcher
        mobile={"render for mobile"}
        // tablet={"tablet"} // mobile will be rendered for "skipped" tablet
        desktop={"render desktop"}
    />
    <MediaMatcher
        mobile={"render for mobile"}
        tablet={null} // nothing will be rendered for tablet, as long you clearly defined it
        desktop={"render desktop"}
    />
    
    <MediaMatches> // will provide matches information via render-props
        {matches => (
            <span> testing {
                // pick matching values
                pickMatch(matches, {
                    mobile: "mobile",
                    // tablet: "tablet", // the same rules are applied here
                    desktop: "desktop",
                })
            }</span>
        )}
    </MediaMatches>
    
    <MediaMatches> // will provide matches information via render-props
            {(_,pickMatch) => ( // you can get pickMatch from MediaMatches
                <span> testing {
                    // pick matching values
                    pickMatch({
                        mobile: "mobile",
                        // tablet: "tablet", // the same rules are applied here
                        desktop: "desktop",
                    })
                }</span>
            )}
        </MediaMatches>
</ProvideMediaMatchers>

PS: Don’t forget to wrap all this with ProvideMediaMatchers - without it MediaMatches will always picks the "last" branch.

Server-Side Rendering

There is no way to support MediaQuery on the Server Side, so the only way to generate the expected result is to mock a predicted device.

We are providing a special component which will mock data only on server size, and compare predicted media on componentMount on client size.

It also has a special prop hydrated which will lead to forced react tree remount in case prediction was wrong, and rendered tree will not match hydrated one. (use only in case of ReactDOM.hydrated)

import { MediaMatcher, MediaServerRender } from "react-media-match";

<MediaServerRender predicted="desktop" hydrated>
    <MediaMatcher
        mobile={"render for mobile"}
        // tablet={"tablet"} // mobile will be rendered for "skipped" tablet
        desktop={"render desktop"}
    />
</MediaServerRender>

If prediction has failed - it will inform you, and might help to mitigate rendering issues.

How to predict device type

You may use ua-parser-js, to detect device type, and pick desired screen resolution, or use react-ugent to make it a bit more declarative.

API

react-media-match provides an API for "default" queries, and a factory method to create custom media queries.

  • createMediaMatcher(breakPoints: { key: string }) - factory for a new API for provided breakpoints. The object with following props will be returned:
    • pickMatch
    • Matches
    • Matcher
    • Provider
    • Mock
    • SSR

There is also pre-exported API for default breakpoints - mobile, tablet, desktop

  • pickMatch(matches, matchers) - function, return value from matchers matching matches.

  • ProvideMediaMatchers - component, calculates media queries and stores them in context.

  • MediaMatches - component, returns current matchers as a render prop

  • MediaMatcher - component, renders path for active match

  • MediaServerRender - component, helps render server-size

Example

  • Define secondary Query for orientation
import { createMediaMatcher } from "react-media-match";

 const Orientation = createMediaMatcher({
   portrait: "(orientation: portrait)",
   landscape: "(orientation: landscape)"
 });

 <Orientation.Match
   portrait="One"
   landscape="Second"
 />
  • Define query based on user settings
import { MediaMock, ProvideMediaMatchers } from "react-media-match";

// override all data
<ProvideMediaMatchers state={{mobile:true, tablet:false, desktop:false}}>
   ....
</ProvideMediaMatchers>

<MediaMock mobile>
    ....
</MediaMock>

<Orientation.Mock portrait>
    ....
</Orientation.Mock>

Sandbox

https://codesandbox.io/s/o7q3zlo0n9

Testing and Mocking

Just provide state for ProvideMediaMatchers, and it will control all the nested matchers. Could be used to provide not media-based rules.

  • ProvideMediaMatchers has a state parameter, and you might specify it override any information, and control all the nested matchers.
  • MediaMock will completely mock media settings.

Both mocks are not working for Inline component.

Testing and mocking are related to SSR rendering, and you may use MediaServerRender for tests and Mocks for SSR as well.

Articles

License

MIT

Readme

Keywords

none

Package Sidebar

Install

npm i @herbco/react-media-match

Weekly Downloads

2

Version

1.4.2

License

ISC

Unpacked Size

26.6 kB

Total Files

17

Last publish

Collaborators

  • corygibbons
  • shanewilson