• Stars
    star
    140
  • Rank 261,473 (Top 6 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 8 years ago
  • Updated about 6 years ago

Reviews

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

Repository Details

Get position and size attributes for any React Component

remeasure

Get position and size of the DOM element for any React Component

Table of contents

Usage

// ES2015
import { measure, Measured } from "remeasure";

// CommonJS
const { measure, Measured } = require("remeasure").default;

// old school script
var measure = window.Remeasure.measure;
var Measured = window.Remeasure.Measured;

As a decorator

@measure
class MyComponent extends React.Component {
  render() {
    const { height, width } = this.props;

    return <div>I have access to my height and width through props!</div>;
  }
}

const StatelessComponent = measure(({ height, width }) => {
  return <div>In here too!</div>;
});

As a component

You can use the component with function-rendering components one of three ways:

// using a children method
const MyMeasuredComponent = () => {
  return (
    <Measured height width>
      {({ height, width }) => {
        return (
          <div>
            My height is {height} and my width is {width}
          </div>
        );
      }}
    </Measured>
  );
};

// using a component method
const MyMeasuredComponent = () => {
  return (
    <Measured
      height
      width
      component={({ height, width }) => {
        return (
          <div>
            My height is {height} and my width is {width}
          </div>
        );
      }}
    />
  );
};

// using a render method
const MyMeasuredComponent = () => {
  return (
    <Measured
      height
      width
      render={({ height, width }) => {
        return (
          <div>
            My height is {height} and my width is {width}
          </div>
        );
      }}
    />
  );
};

For performance reasons, it is recommended that you store the component as a separate method rather than create a method inline:

// using a render method
const Render = ({ height, width }) => {
  return (
    <div>
      My height is {height} and my width is {width}
    </div>
  );
};

const MyMeasuredComponent = () => {
  return <Measured height width render={Render} />;
};

Measurements

The following properties are available for measurement:

{
  bottom: Number,
  clientLeft: Number,
  clientHeight: Number,
  clientWidth: Number,
  clientTop: Number,
  height: Number,
  left: Number,
  naturalHeight: Number,
  naturalWidth: Number,
  offsetHeight: Number,
  offsetLeft: Number,
  offsetTop: Number,
  offsetWidth: Number,
  scrollHeight: Number,
  scrollLeft: Number,
  scrollTop: Number,
  scrollWidth: Number,
  right: Number,
  top: Number
  width: Number
}

The bottom, left, right, and top properties are what you would expect from the result of element.getBoundingClientRect(). naturalHeight and naturalWidth are properties that are native to img elements, and for all non-img elements they are coalesced with scrollHeight and scrollWidth, respectively.

These properties are retrieved on mount, but will also automatically update if the element is resized thanks to ResizeObserver. Please note that elements that do not support content (such as img) are not supported by this resize listener because there is no content box to observe. If you need to support those elements, simply create a higher-order component that wraps that element in a div and decorate that component.

Advanced usage

keys

(Array<string>|string)

The keys to listen for changes to. If not specified, all possible keys will be measured.

Examples:

import measure from "remeasure";

// pass a string value for a single property
const measureOnlyOffsetWidth = measure("offsetWidth");

const MyStatelessComponent = measureOnlyOffsetWidth(({ offsetWidth }) => {
  return <div>Only offsetWidth is injected</div>;
});

// or an array of string values for multiple properties
@measure(["top", "height"])
class MyComponent extends Component {
  render() {
    const { top, height } = this.props;

    return <div>Both the top and height props are injected</div>;
  }
}

You can apply the keys one of two ways on the Measure component:

// either as individual boolean properties
<Measured height>
  {({height}) => {
    return (
      <div>I am {height} pixels in height.</div>
    );
  }}
</Measured>

// or as the "keys" prop
<Measured keys={['height']}>
  {({height}) => {
    return (
      <div>I am {height} pixels in height.</div>
    );
  }}
</Measured>

Note that the properties will only be applied if they are set to true (yes, you can actually toggle what properties are measured!).

options

Object

Allows customization of the measurements. Available options:

{
    // value in milliseconds to debounce rerenders
    debounce: Number,

    // sets namespace for values to be passed into props on
    namespace: String,

    // should element rerender when resized
    renderOnResize: Boolean = true

    // should element rerender when the window is resized
    renderOnWindowResize: Boolean = false
}

Example usage with the decorator:

// use them alone
@measure({ renderOnResize: false })
class MyComponent extends Component {
  render() {
    const { height, width } = this.props;

    return <div>The height and width props will not update with resizes.</div>;
  }
}

// or you can use them with keys
const MyStatelessComponent = measure(["height", "width"], {
  debounce: 50,
  namespace: "measurements"
})(({ measurements }) => {
  return (
    <div>
      You can still pass options when you want to specify keys, as the second
      parameter.
    </div>
  );
});

Example usage with the Measured component:

<Measured debounce={500} namespace="measurements">
  {({ measurements }) => {
    return <div>My measurements: {JSON.stringify(measurements)}</div>;
  }}
</Measured>

ref

Like any other component, you can access the Measured component instance via the ref, but when using the measure decorator you will be accessing the Measured HOC and not the original component. If you want to access the original component, it is available as the originalComponent property on that ref.

@measure.width
class Foo extends Component {
  getProps() {
    return this.props;
  }

  render() {
    return <div>Use getProps to get my props!</div>;
  }
}
...
class FooConsumer extends Component {
  componentDidMount() {
    console.log(this.foo); // Measured component
    console.log(this.foo.originalComponent); // Foo component
    console.log(this.foo.originalComponent.getProps()); // {bar: 'bar'}
  }

  render() {
    <Foo
      ref={(component) => {
        this.foo = component;
      }}
      bar="bar"
    />
  }
}

Convenience methods

For each key that is measured, a convenience function exists on the measure decorator. Example:

@measure.width
class MyMeasuredComponent extends Component {
  render() {
    const { width } = this.props;

    return <div>I have width of {width}.</div>;
  }
}

Caveats

A couple things to keep in mind when using remeasure:

Void tags cannot detect element resize

If children on a tag are considered invalid HTML (such as for <input/>, <img/>, etc), then the internal element resize detector cannot work. The easy solution to this is to update the component via props (on update, a recalculation of values is triggered).

Components may render twice on update

If you perform an update to the component props or state that also happens to change its dimensions, the component will update twice, once for the changes to props / state, and again for the changes to its dimensions. This is because the component needs to render in the DOM before updated values can be calculated.

Support

remeasure has been tested and confirmed to work on the following browsers:

  • Chrome
  • Firefox
  • Opera
  • Edge
  • IE9+

remeasure also works with universal / isomorphic applications.

Development

Standard stuff, clone the repo and npm i to get the dependencies. npm scripts available:

  • build => builds the distributed JS with NODE_ENV=development and with sourcemaps
  • build-minified => builds the distributed JS with NODE_ENV=production and minified
  • compile-for-publish => runs the lint, test, transpile, dist scripts
  • dev => runs the webpack dev server for the playground
  • dist => runs the build and build-minified
  • lint => runs ESLint against files in the src folder
  • prepublish => if in publish, runs compile-for-publish
  • test => run ava with NODE_ENV=test
  • test:watch => runs test but with persistent watcher
  • transpile => runs Babel against files in src to files in lib

More Repositories

1

fast-copy

A blazing fast deep object copier
JavaScript
1,133
star
2

moize

The consistently-fast, complete memoization solution for JS
TypeScript
892
star
3

fast-equals

A blazing fast equality comparison, either shallow or deep
TypeScript
471
star
4

unchanged

A tiny, fast, unopinionated handler for updating JS objects and arrays immutably
TypeScript
240
star
5

micro-memoize

A tiny, crazy fast memoization library for the 95% use-case
TypeScript
238
star
6

crio

Immutable objects and arrays in a natural way
JavaScript
211
star
7

hash-it

Hash any object type based on its values
TypeScript
206
star
8

inline-loops.macro

Iteration helpers that inline to native loops for performance
JavaScript
100
star
9

selectorator

Simple generator of reselect selectors
TypeScript
96
star
10

react-style-tag

Write styles declaratively in React
TypeScript
68
star
11

react-pure-lifecycle

JavaScript
65
star
12

react-windowed-list

JavaScript
61
star
13

jile

Modular CSS in pure JavaScript
JavaScript
59
star
14

react-vidz-player

HTML5 videos in a React way
JavaScript
53
star
15

fast-stringify

A blazing fast stringifier that safely handles circular objects
TypeScript
51
star
16

react-billboardjs

React component for the billboard.js charting library
JavaScript
45
star
17

curriable

Curry any function with placeholder support
TypeScript
38
star
18

vidz

A zero-dependency, framework-agnostic video implementation
JavaScript
37
star
19

switchem

An extensible, functional switch with a chainable API
JavaScript
35
star
20

waddup

A ridiculously tiny pubsub manager with no dependencies
JavaScript
27
star
21

benchee

Simple benchmarks in both node and browser
TypeScript
27
star
22

react-local-redux

Manage component-specific state as you would global state via redux
JavaScript
23
star
23

arco

JavaScript
22
star
24

flexor

JavaScript
21
star
25

qonductor

Manage your data processing with sanity
JavaScript
19
star
26

react-parm

Handle react class instances with more functional purity
JavaScript
18
star
27

react-rendered-size

Get the rendered size of a React element without needing to render it
JavaScript
17
star
28

kari

JavaScript
14
star
29

pathington

JavaScript
13
star
30

get-object-class

A more explicit improvement on typeof
JavaScript
12
star
31

redux-browser-storage

Use redux to manage localStorage and sessionStorage data
JavaScript
11
star
32

remodeled

An abstraction for the React API with functional purity
JavaScript
11
star
33

convertify

Easily convert from one object class to the next
JavaScript
10
star
34

nage

Efficient, tiny object pool
TypeScript
9
star
35

tcf

A functional try / catch / finally with async support
JavaScript
8
star
36

bolster-css

JavaScript
7
star
37

printscout

Handle print events with ease
JavaScript
7
star
38

pure-object

JavaScript
7
star
39

react-jile

JavaScript
7
star
40

highcharts-config

Declarative Highcharts configuration generator with immutable, chainable API
JavaScript
6
star
41

react-idle-manager

JavaScript
6
star
42

react-redux-partitioner

Distribute state management for more performant reactivity
TypeScript
5
star
43

repoll

JavaScript
5
star
44

isit.js

Micro check library
JavaScript
4
star
45

identitate

Custom identity functions for composability
JavaScript
4
star
46

retip

A simple react tooltip
JavaScript
3
star
47

redux-slices

Manage slices of redux store in a concise, clear way
HTML
2
star
48

utilities

A collection of utilities used across projects
JavaScript
2
star
49

doozy

Transducer library for arrays, objects, sets, and maps
JavaScript
2
star
50

what-am-i

Simple validation library
TypeScript
2
star
51

promise-polyfill

Promise polyfill with custom opt-in error handling for debug
TypeScript
1
star
52

bolster

Library to augment jQuery with additional functionality
JavaScript
1
star
53

memzee

Function memoization based on only the most recent arguments
TypeScript
1
star
54

isifier

Make your own tiny, targeted validation library
JavaScript
1
star
55

diviso

Simple, flexible state management
1
star
56

singulum

State management with sanity
JavaScript
1
star
57

planttheidea.github.io

Github IO site for planttheidea
JavaScript
1
star