• Stars
    star
    1,935
  • Rank 23,945 (Top 0.5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Make your React Components aware of their width and height!

 

Make your React Components aware of their width and/or height!

 

npm MIT License Travis Codecov

  • Hyper Responsive Components!
  • Performant.
  • Easy to use.
  • Extensive browser support.
  • Supports functional and class Component types.
  • Tiny bundle size.
  • Demo: https://4mkpc.csb.app/

Use it via the render prop pattern (supports children or render prop):

import { SizeMe } from 'react-sizeme'

function MyApp() {
  return <SizeMe>{({ size }) => <div>My width is {size.width}px</div>}</SizeMe>
}

Or, via a higher order component:

import { withSize } from 'react-sizeme'

function MyComponent({ size }) {
  return <div>My width is {size.width}px</div>
}

export default withSize()(MyComponent)

 


TOCs

 


Intro

Give your Components the ability to have render logic based on their height and/or width. Responsive design on the Component level. This allows you to create highly reusable components that can adapt to wherever they are rendered.

Check out a working demo here: https://4mkpc.csb.app/

 


Installation

Firstly, ensure you have the required peer dependencies:

npm install react react-dom

Note: We require >[email protected] and >[email protected]

npm install react-sizeme

 


Configuration

The following configuration options are available. Please see the usage docs for how to pass these configuration values into either the component or higher order function.

  • monitorWidth (boolean, default: true)

    If true, then any changes to your Components rendered width will cause an recalculation of the "size" prop which will then be be passed into your Component.

  • monitorHeight (boolean, default: false)

    If true, then any changes to your Components rendered height will cause an recalculation of the "size" prop which will then be be passed into your Component.

    PLEASE NOTE: that this is set to false by default

  • refreshRate (number, default: 16)

    The maximum frequency, in milliseconds, at which size changes should be recalculated when changes in your Component's rendered size are being detected. This should not be set to lower than 16.

  • refreshMode (string, default: 'throttle')

    The mode in which refreshing should occur. Valid values are "debounce" and "throttle".

    "throttle" will eagerly measure your component and then wait for the refreshRate to pass before doing a new measurement on size changes.

    "debounce" will wait for a minimum of the refreshRate before it does a measurement check on your component.

    "debounce" can be useful in cases where your component is animated into the DOM.

    NOTE: When using "debounce" mode you may want to consider disabling the placeholder as this adds an extra delay in the rendering time of your component.

  • noPlaceholder (boolean, default: false)

    By default we render a "placeholder" component initially so we can try and "prefetch" the expected size for your component. This is to avoid any unnecessary deep tree renders. If you feel this is not an issue for your component case and you would like to get an eager render of your component then disable the placeholder using this config option.

    NOTE: You can set this globally. See the docs on first render.

 


Component Usage

We provide a "render props pattern" based component. You can import it like so:

import { SizeMe } from 'react-sizeme'

You then provide it either a render or children prop containing a function/component that will receive a size prop (an object with width and height properties):

<SizeMe>{({ size }) => <div>My width is {size.width}px</div>}</SizeMe>

or

<SizeMe render={({ size }) => <div>My width is {size.width}px</div>} />

To provide configuration you simply add any customisation as props. For example:

<SizeMe
  monitorHeight
  refreshRate={32}
  render={({ size }) => <div>My width is {size.width}px</div>}
/>

 


HOC Usage

We provide you with a higher order component function called withSize. You can import it like so:

import { withSize } from 'react-sizeme'

Firstly, you have to call the withSize function, passing in an optional configuration object should you wish to customise the behaviour:

const withSizeHOC = withSize()

You can then use the returned Higher Order Component to decorate any of your existing Components with the size awareness ability:

const SizeAwareComponent = withSizeHOC(MyComponent)

Your component will then receive a size prop (an object with width and height properties).

Note that the values could be undefined based on the configuration you provided (e.g. you explicitly do not monitor either of the dimensions)

Below is a full example:

import { withSize } from 'react-sizeme'

class MyComponent extends Component {
  render() {
    const { width, height } = this.props.size

    return (
      <div>
        My size is {width || -1}px x {height || -1}px
      </div>
    )
  }
}

export default withSize({ monitorHeight: true })(MyComponent)

onSize callback alternative usage

The higher order component also allows an alternative usage where you provide an onSize callback function.

This allows the "parent" to manage the size value rather than your component, which can be useful in specific circumstances.

Below is an example of it's usage.

Firstly, create a component you wish to know the size of:

import { withSize } from 'react-sizeme'

function MyComponent({ message }) {
  return <div>{message}</div>
}

export default withSize()(MyComponent)

Now create a "parent" component providing it a onSize callback function to the size aware component:

class ParentComponent extends React.Component {
  onSize = (size) => {
    console.log('MyComponent has a width of', size.width)
  }

  render() {
    return <MyComponent message="Hello world" onSize={this.onSize} />
  }
}

 


Under the hood

It can be useful to understand the rendering workflow should you wish to debug any issues we may be having.

In order to size your component we have a bit of a chicken/egg scenario. We can't know the width/height of your Component until it is rendered. This can lead wasteful rendering cycles should you choose to render your components based on their width/height.

Therefore for the first render of your component we actually render a lightweight placeholder in place of your component in order to obtain the width/height. If your component was being passed a className or style prop then these will be applied to the placeholder so that it can more closely resemble your actual components dimensions.

So the first dimensions that are passed to your component may not be "correct" dimensions, however, it should quickly receive the "correct" dimensions upon render.

Should you wish to avoid the render of a placeholder and have an eager render of your component then you can use the noPlaceholder configuration option. Using this configuration value your component will be rendered directly, however, the size prop may contain undefined for width and height until your component completes its first render.

 


Examples

Loading different child components based on size

import React from 'react'
import LargeChildComponent from './LargeChildComponent'
import SmallChildComponent from './SmallChildComponent'
import sizeMe from 'react-sizeme'

function MyComponent(props) {
  const { width, height } = props.size

  const ToRenderChild = height > 600 ? LargeChildComponent : SmallChildComponent

  return (
    <div>
      <h1>
        My size is {width}x{height}
      </div>
      <ToRenderChild />
    </div>
  )
}

export default sizeMe({ monitorHeight: true })(MyComponent)

EXTRA POINTS! Combine the above with a code splitting API (e.g. Webpack's System.import) to avoid unnecessary code downloads for your clients. Zing!

 


Server Side Rendering

Okay, I am gonna be up front here and tell you that using this library in an SSR context is most likely a bad idea. If you insist on doing so you then you should take the time to make yourself fully aware of any possible repercussions you application may face.

A standard sizeMe configuration involves the rendering of a placeholder component. After the placeholder is mounted to the DOM we extract it's dimension information and pass it on to your actual component. We do this in order to avoid any unnecessary render cycles for possibly deep component trees. Whilst this is useful for a purely client side set up, this is less than useful for an SSR context as the delivered page will contain empty placeholders. Ideally you want actual content to be delivered so that users without JS can still have an experience, or SEO bots can scrape your website.

To avoid the rendering of placeholders in this context you can make use of the noPlaceholders global configuration value. Setting this flag will disables any placeholder rendering. Instead your wrapped component will be rendered directly - however it's initial render will contain no values within the size prop (i.e. width, and height will be null).

import sizeMe from 'react-sizeme'

// This is a global variable. i.e. will be the default for all instances.
sizeMe.noPlaceholders = true

Note: if you only partialy server render your application you may want to use the component level configuration that allows disabling placeholders per component (e.g. sizeMe({ noPlaceholder: true }))

It is up to you to decide how you would like to initially render your component then. When your component is sent to the client and mounted to the DOM SizeMe will calculate and send the dimensions to your component as normal. I suggest you tread very carefully with how you use this updated information and do lots of testing using various screen dimensions. Try your best to avoid unnecessary re-rendering of your components, for the sake of your users.

If you come up with any clever strategies for this please do come share them with us! :)

 


Extreme Appreciation!

We make use of the awesome element-resize-detector library. This library makes use of an scroll/object based event strategy which outperforms window resize event listening dramatically. The original idea for this approach comes from another library, namely css-element-queries by Marc J. Schmidt. I recommend looking into these libraries for history, specifics, and more examples. I love them for the work they did, whithout which this library would not be possible. 💖

 


Backers

Thank goes to all our backers! [Become a backer].

More Repositories

1

easy-peasy

Vegetarian friendly state for React
JavaScript
5,029
star
2

react-universally

A starter kit for universal react applications.
JavaScript
1,694
star
3

react-async-component

Resolve components asynchronously, with support for code splitting and advanced server side rendering use cases.
JavaScript
1,446
star
4

react-tree-walker

Walk a React (or Preact) element tree, executing a "visitor" function against each element.
JavaScript
345
star
5

react-component-queries

Provide props to your React Components based on their Width and/or Height.
JavaScript
183
star
6

react-jobs

Asynchronously resolve data for your components, with support for server side rendering.
JavaScript
166
star
7

react-async-bootstrapper

Execute a bootstrap method on your React/Preact components. Useful for data prefetching and other activities.
JavaScript
118
star
8

code-split-component

Declarative code splitting for your Wepback bundled React projects, with SSR support.
JavaScript
116
star
9

prisma-pg-jest

Example showcasing how to use Prisma + Postgres + Jest, where each test has its own unique DB context
TypeScript
103
star
10

react-virtual-container

Optimise your React apps by only rendering components when in proximity to the viewport.
JavaScript
53
star
11

cra-monorepo

Example of a now 2.0 monorepo containing Create React App and Node Lambdas
TypeScript
53
star
12

vercel-node-server

An unofficial package allowing you to create http.Server instances of your Vercel Node lambdas.
TypeScript
50
star
13

react-injectables

Explicitly inject Components into any part of your React render tree.
JavaScript
44
star
14

easy-peasy-typescript

An example of using Easy Peasy with Typescript
TypeScript
33
star
15

react-universally-skinny

A "when size matters" adaptation of the react-universally boilerplate.
JavaScript
30
star
16

lerna-cola

Superpowers for your Lerna monorepos.
JavaScript
23
star
17

gun-most

Extends gunDB with the ability to chain into most.js observables.
JavaScript
14
star
18

i-theme

A minimalist theme for vscode
12
star
19

preact-compat-hmr

Example HMR with preact, preact-compat and webpack 2.
JavaScript
12
star
20

prisma2-template

A scratchpad for Prisma2
JavaScript
12
star
21

vercel-node-dev

An unofficial development CLI for Vercel applications targeting the Node.js runtime.
TypeScript
10
star
22

vue-zod-form

A composition based API forms helper for Vue 3 projects that utilise TypeScript.
Vue
10
star
23

npm-library-starter

A starter kit for npm libraries.
JavaScript
9
star
24

vue3-typescript-strategy

An example of a sound TS experience in Vue 3 via .tsx files
TypeScript
8
star
25

cinderella

[WIP] A tiny transformation library.
JavaScript
8
star
26

demo-react-async-and-jobs

Demo on how to use react-async-component and react-jobs together in an SSR project.
JavaScript
7
star
27

react-universally-opinionated

[WIP] An opinionated version of React, Universally.
JavaScript
7
star
28

simee

Ultra simple symlinking of local npm packages.
JavaScript
7
star
29

remix-aws-edge

An adapter for running Remix on AWS CloudFront Lambda@Edge
TypeScript
6
star
30

easy-peasy-hot-reload

Easy Peasy hot reloading example
HTML
6
star
31

easy-peasy-website

Official docs for easy-peasy
5
star
32

react-hey-fela

Alternative React bindings for Fela
JavaScript
4
star
33

templatiser

Apply templates to a file tree.
JavaScript
4
star
34

react-app-rewire-modernizr

Adds the modernizr-loader to your react-app-rewired config.
JavaScript
3
star
35

reason-advent-2017

https://adventofcode.com solved using ReasonML
OCaml
2
star
36

comickult.holding

RxJS powered holding page for comickult.
JavaScript
2
star
37

code-split-match

A Webpack 2 code splitting Match component for React Router v4.
2
star
38

flowcheatsheet

An interactive cheat sheet for Facebook's Flow type system.
JavaScript
2
star
39

lerna-cola-sample

A sample application showcasing Lerna Cola
JavaScript
2
star
40

react-app-rewire-css-blocks

Adds support for CSS Blocks to your react-app-rewired config.
JavaScript
2
star
41

react-universally-archive

JavaScript
2
star
42

now-dev-issue

JavaScript
1
star
43

reason-react-gof

[WIP] Conway's Game of Life implemented using ReasonML/Bucklescript/React.
OCaml
1
star
44

sst-cors-example

An example of CORS configuration in the context of a Serverless Stack application.
TypeScript
1
star
45

splice

A malleable content management system.
1
star
46

react-responsive-element

A responsive element component for React web applications.
1
star
47

blank

Blank project for fiddling with JS whilst having all the tooling I like
JavaScript
1
star
48

react-router-bundlesize

Debugging react-router bundle size optimisation.
JavaScript
1
star
49

react-fractal-grid

A fractal grid Component set for React.
1
star
50

approachable-fp-in-scala

An Approachable Guide to Functional Programming in Scala
1
star
51

monilla

A CLI to manage monorepos with predictability and stability.
TypeScript
1
star