{"id":13468704,"url":"https://github.com/renatorib/react-sizes","last_synced_at":"2025-05-15T17:03:53.481Z","repository":{"id":19733483,"uuid":"87744817","full_name":"renatorib/react-sizes","owner":"renatorib","description":":left_right_arrow: Hoc to easily map window sizes to props.","archived":false,"fork":false,"pushed_at":"2022-12-09T15:40:55.000Z","size":1422,"stargazers_count":717,"open_issues_count":20,"forks_count":36,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-09T05:01:50.203Z","etag":null,"topics":["high-order-component","hoc","media-queries","react","responsive"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/renatorib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-09T22:42:00.000Z","updated_at":"2025-03-23T18:16:37.000Z","dependencies_parsed_at":"2023-01-14T07:45:48.542Z","dependency_job_id":null,"html_url":"https://github.com/renatorib/react-sizes","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renatorib%2Freact-sizes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renatorib%2Freact-sizes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renatorib%2Freact-sizes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renatorib%2Freact-sizes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/renatorib","download_url":"https://codeload.github.com/renatorib/react-sizes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254384983,"owners_count":22062422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["high-order-component","hoc","media-queries","react","responsive"],"created_at":"2024-07-31T15:01:17.084Z","updated_at":"2025-05-15T17:03:53.466Z","avatar_url":"https://github.com/renatorib.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"![react-sizes](./logo.png)\n\n[![npm](https://img.shields.io/npm/v/react-sizes.svg?style=flat-square)](https://www.npmjs.com/package/react-sizes)\n[![npm](https://img.shields.io/npm/dt/react-sizes.svg?style=flat-square)](https://www.npmjs.com/package/react-sizes)\n[![GitHub issues](https://img.shields.io/github/issues/renatorib/react-sizes.svg?style=flat-square)](https://github.com/renatorib/react-sizes/issues)\n[![GitHub stars](https://img.shields.io/github/stars/renatorib/react-sizes.svg?style=flat-square)](https://github.com/renatorib/react-sizes/stargazers)\n[![Twitter](https://img.shields.io/twitter/url/https/github.com/renatorib/react-sizes.svg?style=social\u0026style=flat-square)](https://twitter.com/intent/tweet?url=https://github.com/renatorib/react-sizes)\n\n## Install\n\n```\nyarn add react-sizes\n```\n\n```\nnpm install react-sizes\n```\n\n## What and why\n\nReact Sizes is a higher-order component with strong performance that transforms window sizes (width and height) into props.  \nYou can check inside your component, for example, if user's window is less than 480 pixels of width, and add a custom\ncontent.\n\nIt can be very powerful for when you need to display different content for mobile and desktop.\nBut it's not limited to this case. Just use that at your needs.\n\n## Usage\n\n#### With class component.\n\n```jsx\nimport React, { Component } from 'react'\nimport withSizes from 'react-sizes'\n\nclass MyComponent extends Component {\n  render() {\n    return \u003cdiv\u003e{this.props.isMobile ? 'Is Mobile' : 'Is Not Mobile'}\u003c/div\u003e\n  }\n}\n\nconst mapSizesToProps = ({ width }) =\u003e ({\n  isMobile: width \u003c 480,\n})\n\nexport default withSizes(mapSizesToProps)(MyComponent)\n```\n\nYou can play with this example [here](https://codesandbox.io/s/Rg0DDOWnE).\n\n#### As decorator.\n\n```jsx\nimport React from 'react'\nimport withSizes from 'react-sizes'\n\n@withSizes(({ width }) =\u003e ({ isMobile: width \u003c 480 }))\nclass MyComponent extends Component {\n  render() {\n    return \u003cdiv\u003e{this.props.isMobile ? 'Is Mobile' : 'Is Not Mobile'}\u003c/div\u003e\n  }\n}\n\nexport default MyComponent\n```\n\n#### Interoperate with other libraries.\n\n```jsx\nimport React from 'react'\nimport withSizes from 'react-sizes'\nimport { withState, compose } from 'recompose'\n\nconst enhancer = compose(\n  withState('counter', 'setCounter', 0),\n  withSizes(({ width }) =\u003e ({ isMobile: width \u003c 480 }))\n)\n\nconst MyComponent = enhancer(({ isMobile, counter, setCounter }) =\u003e (\n  \u003cdiv\u003e\n    \u003cdiv\u003e\n      Count: {counter}{' '}\n      \u003cbutton onClick={() =\u003e setCounter(n =\u003e n + 1)}\u003eIncrement\u003c/button\u003e\n    \u003c/div\u003e\n    \u003cdiv\u003e{isMobile ? 'Is Mobile' : 'Is Not Mobile'}\u003c/div\u003e\n  \u003c/div\u003e\n))\n\nexport default MyComponent\n```\n\n#### With functional component.\n\n```jsx\nimport React from 'react'\nimport withSizes from 'react-sizes'\n\nconst MyComponent = ({ isMobile }) =\u003e (\n  \u003cdiv\u003e{isMobile ? 'Is Mobile' : 'Is Not Mobile'}\u003c/div\u003e\n)\n\nconst mapSizesToProps = ({ width }) =\u003e ({\n  isMobile: width \u003c 480,\n})\n\nexport default withSizes(mapSizesToProps)(MyComponent)\n```\n\n#### Mess with props.\n\n(Added in 0.1.0)\n\n```jsx\nimport React from 'react'\nimport withSizes from 'react-sizes'\n\nconst MyComponent = ({ isMobile }) =\u003e (\n  \u003cdiv\u003e{isMobile ? 'Is Mobile' : 'Is Not Mobile'}\u003c/div\u003e\n)\n\nconst mapSizesToProps = ({ width }, { mobileBreakpoint }) =\u003e ({\n  isMobile: width \u003c mobileBreakpoint,\n})\n\nexport default withSizes(mapSizesToProps)(MyComponent)\n```\n\nthen:\n\n```jsx\n\u003cMyComponent mobileBreakpoint={480} /\u003e\n\u003cMyComponent mobileBreakpoint={400} /\u003e\n\u003cMyComponent mobileBreakpoint={600} /\u003e\n```\n\n#### With presets selectors.\n\n```diff\n- const mapSizesToProps = ({ width }) =\u003e ({\n-   isMobile: width \u003c 480,\n- });\n\n+ const mapSizesToProps = sizes =\u003e ({\n+  isMobile: withSizes.isMobile(sizes),\n+ });\n```\n\n## Presets Selectors\n\nYou can check all **our** presets selectors at our main code `src/withSizes.js`.\n\n```js\nwithSizes.isMobile = ({ width }) =\u003e width \u003c 480\nwithSizes.isTablet = ({ width }) =\u003e width \u003e= 480 \u0026\u0026 width \u003c 1024\nwithSizes.isDesktop = ({ width }) =\u003e width \u003e= 1024\n\nwithSizes.isGtMobile = sizes =\u003e !withSizes.isMobile(sizes)\nwithSizes.isGtTablet = sizes =\u003e withSizes.isDesktop(sizes)\n\nwithSizes.isStTablet = sizes =\u003e withSizes.isMobile(sizes)\nwithSizes.isStDesktop = sizes =\u003e !withSizes.isStDesktop(sizes)\n\nwithSizes.isTabletAndGreater = sizes =\u003e !withSizes.isMobile(sizes)\nwithSizes.isTabletAndSmaller = sizes =\u003e !withSizes.isStDesktop(sizes)\n```\n\nIf it don't fit to your needs, you can create your own selectors.\n\n```jsx\n// utils/sizes/selectors.js\nexport const isntDesktop = ({ width }) =\u003e width \u003c 1024\nexport const backgroundColor = ({ width }) =\u003e (width \u003c 480 ? 'red' : 'green')\n\n// your component\nimport { isntDesktop, backgroundColor } from 'utils/sizes/selectors'\n\nconst mapSizesToProps = sizes =\u003e ({\n  canDisplayMobileFeature: isntDesktop(sizes),\n  backgroundColor: backgroundColor(sizes),\n})\n```\n\n\u003e `sizes` argument is an object with `width` and `height` properties and represents DOM window width and height.\n\n## Guide\n\n#### mapSizesToProps(sizes)\n\n`sizes` argument is an object with `width` and `height` of DOM window.\n\n```js\nconst mapSizesToProps = sizes =\u003e {\n  console.log(sizes) // { width: 1200, height: 720 } (example)\n}\n```\n\nIn pratice, it is a callback that return props that will injected into your Component.\n\n```js\nconst mapSizesToProps = function(sizes) {\n  const props = {\n    backgroundColor: sizes.width \u003c 700 ? 'red' : 'green',\n  }\n\n  return props\n}\n```\n\nBut you can simplify this to stay practical and elegant.\n\n```js\nconst mapSizesToProps = ({ width }) =\u003e ({\n  backgroundColor: width \u003c 700 ? 'red' : 'green',\n})\n```\n\n## Server Side Rendering\n\nSince 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.  \nBut be careful, **user-agent based detection is not a reliable solution**. It's a workaround.\n\n```js\n// Config can be created based on user-agent. See below\nconst config = { fallbackWidth: 360, fallbackHeight: 640 }\n\nreturn (\n  \u003cSizesProvider config={config}\u003e\n    \u003cApp /\u003e\n  \u003c/SizesProvider\u003e\n)\n```\n\nExample:\n\n```js\nimport MobileDetect from 'mobile-detect'\nimport Express from 'express'\nimport { SizesProvider } from 'react-sizes'\n// All other imports\n\nconst getSizesFallback = userAgent =\u003e {\n  const md = new MobileDetect(userAgent)\n\n  if (!!md.mobile()) {\n    return {\n      fallbackWidth: 360,\n      fallbackHeight: 640,\n    }\n  } else if (!!md.tablet()) {\n    return {\n      fallbackWidth: 768,\n      fallbackHeight: 1024,\n    }\n  }\n\n  return {\n    fallbackWidth: 1280,\n    fallbackHeight: 700,\n  }\n}\n\n// Note: you don't need to use express, this is just an example\nconst app = new Express()\napp.use((req, res) =\u003e {\n  // ...\n  const sizesConfig = getSizesFallback(req.headers['user-agent'])\n\n  const App = (\n    \u003cAnotherProvider\u003e\n      \u003cRouter location={req.url}\u003e\n        \u003cSizesProvider config={sizesConfig}\u003e\n          \u003cRoot /\u003e\n        \u003c/SizesProvider\u003e\n      \u003c/Router\u003e\n    \u003c/AnotherProvider\u003e\n  )\n\n  res.status(200)\n  res.send(`\u003c!doctype html\u003e\\n${ReactDOM.renderToString(\u003cApp /\u003e)}`)\n  res.end()\n})\n\napp.listen(/* ... */)\n```\n\n## Performance Notes\n\n#### Shallow Compare\n\nReact 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.\n\n## Contribute\n\nYou can help improving this project sending PRs and helping with issues.  \nAlso you ping me at [Twitter](http://twitter.com/renatorib_)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frenatorib%2Freact-sizes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frenatorib%2Freact-sizes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frenatorib%2Freact-sizes/lists"}