npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-sizes

v2.0.0

Published

Hoc to easily map window sizes to props.

Downloads

29,870

Readme

react-sizes

npm npm GitHub issues GitHub stars Twitter

Install

yarn add react-sizes
npm install react-sizes

What and why

React Sizes is a high-order component with a high performance that transform window sizes (width and height) into props.
You can check inside your component, for example, if user's window is less than 480 pixels of width, and add a custom content.

It can be very powerful for when you need to display different content for mobile and desktop. But it's not limited to this case. Just use that at your needs.

Usage

With class component.

import React, { Component } from 'react'
import withSizes from 'react-sizes'

class MyComponent extends Component {
  render() {
    return <div>{this.props.isMobile ? 'Is Mobile' : 'Is Not Mobile'}</div>
  }
}

const mapSizesToProps = ({ width }) => ({
  isMobile: width < 480,
})

export default withSizes(mapSizesToProps)(MyComponent)

You can play with this example here.

As decorator.

import React from 'react'
import withSizes from 'react-sizes'

@withSizes(({ width }) => ({ isMobile: width < 480 }))
class MyComponent extends Component {
  render() {
    return <div>{this.props.isMobile ? 'Is Mobile' : 'Is Not Mobile'}</div>
  }
}

export default MyComponent

Interoperate with other libraries.

import React from 'react'
import withSizes from 'react-sizes'
import { withState, compose } from 'recompose'

const enhancer = compose(
  withState('counter', 'setCounter', 0),
  withSizes(({ width }) => ({ isMobile: width < 480 }))
)

const MyComponent = enhancer(({ isMobile, counter, setCounter }) => (
  <div>
    <div>
      Count: {counter}{' '}
      <button onClick={() => setCounter(n => n + 1)}>Increment</button>
    </div>
    <div>{isMobile ? 'Is Mobile' : 'Is Not Mobile'}</div>
  </div>
))

export default MyComponent

With functional component.

import React from 'react'
import withSizes from 'react-sizes'

const MyComponent = ({ isMobile }) => (
  <div>{isMobile ? 'Is Mobile' : 'Is Not Mobile'}</div>
)

const mapSizesToProps = ({ width }) => ({
  isMobile: width < 480,
})

export default withSizes(mapSizesToProps)(MyComponent)

Mess with props.

(Added in 0.1.0)

import React from 'react'
import withSizes from 'react-sizes'

const MyComponent = ({ isMobile }) => (
  <div>{isMobile ? 'Is Mobile' : 'Is Not Mobile'}</div>
)

const mapSizesToProps = ({ width }, { mobileBreakpoint }) => ({
  isMobile: width < mobileBreakpoint,
})

export default withSizes(mapSizesToProps)(MyComponent)

then:

<MyComponent mobileBreakpoint={480} />
<MyComponent mobileBreakpoint={400} />
<MyComponent mobileBreakpoint={600} />

With presets selectors.

- const mapSizesToProps = ({ width }) => ({
-   isMobile: width < 480,
- });

+ const mapSizesToProps = sizes => ({
+  isMobile: withSizes.isMobile(sizes),
+ });

Presets Selectors

You can check all our presets selectors at our main code src/withSizes.js.

withSizes.isMobile = ({ width }) => width < 480
withSizes.isTablet = ({ width }) => width >= 480 && width < 1024
withSizes.isDesktop = ({ width }) => width >= 1024

withSizes.isGtMobile = sizes => !withSizes.isMobile(sizes)
withSizes.isGtTablet = sizes => withSizes.isDesktop(sizes)

withSizes.isStTablet = sizes => withSizes.isMobile(sizes)
withSizes.isStDesktop = sizes => !withSizes.isStDesktop(sizes)

withSizes.isTabletAndGreater = sizes => !withSizes.isMobile(sizes)
withSizes.isTabletAndSmaller = sizes => !withSizes.isStDesktop(sizes)

If it don't fit to your needs, you can create your own selectors.

// utils/sizes/selectors.js
export const isntDesktop = ({ width }) => width < 1024
export const backgroundColor = ({ width }) => (width < 480 ? 'red' : 'green')

// your component
import { isntDesktop, backgroundColor } from 'utils/sizes/selectors'

const mapSizesToProps = sizes => ({
  canDisplayMobileFeature: isntDesktop(sizes),
  backgroundColor: backgroundColor(sizes),
})

sizes argument is an object with width and height properties and represents DOM window width and height.

Guide

mapSizesToProps(sizes)

sizes argument is an object with width and height of DOM window.

const mapSizesToProps = sizes => {
  console.log(sizes) // { width: 1200, height: 720 } (example)
}

In pratice, it is a callback that return props that will injected into your Component.

const mapSizesToProps = function(sizes) {
  const props = {
    backgroundColor: sizes.width < 700 ? 'red' : 'green',
  }

  return props
}

But you can simplify this to stay practical and elegant.

const mapSizesToProps = ({ width }) => ({
  backgroundColor: width < 700 ? 'red' : 'green',
})

Server Side Rendering

Since React Sizes rely on window to computate sizes, we can't computate the values in server enviroment. To try to get around this we can guess user viewport based on your user-agent, and pass values by a Context Provider.
But be careful, user-agent based detection is not a reliable solution. It's a workaround.

// Config can be created based on user-agent. See below
const config = { fallbackWidth: 360, fallbackHeight: 640 }

return (
  <SizesProvider config={config}>
    <App />
  </SizesProvider>
)

Example:

import MobileDetect from 'mobile-detect'
import Express from 'express'
import { SizesProvider } from 'react-sizes'
// All other imports

const getSizesFallback = userAgent => {
  const md = new MobileDetect(userAgent)

  if (!!md.mobile()) {
    return {
      fallbackWidth: 360,
      fallbackHeight: 640,
    }
  } else if (!!md.tablet()) {
    return {
      fallbackWidth: 768,
      fallbackHeight: 1024,
    }
  }

  return {
    fallbackWidth: 1280,
    fallbackHeight: 700,
  }
}

// Note: you don't need to use express, this is just an example
const app = new Express()
app.use((req, res) => {
  // ...
  const sizesConfig = getSizesFallback(req.headers['user-agent'])

  const App = (
    <AnotherProvider>
      <Router location={req.url}>
        <SizesProvider config={sizesConfig}>
          <Root />
        </SizesProvider>
      </Router>
    </AnotherProvider>
  )

  res.status(200)
  res.send(`<!doctype html>\n${ReactDOM.renderToString(<App />)}`)
  res.end()
})

app.listen(/* ... */)

Performance Notes

Shallow Compare

React Sizes do a shallow compare in props generated from mapSizesToProps (called propsToPass), so it will only rerender when they really change. If you create a deep data sctructure, this can generate false positives. In these cases, we recommend using immutable for a more reliable shallow compare result. Or just don't use deep data structures, if possible.

Contribute

You can help improving this project sending PRs and helping with issues.
Also you ping me at Twitter