GithubHelp home page GithubHelp logo

ctrlplusb / react-sizeme Goto Github PK

View Code? Open in Web Editor NEW
1.9K 15.0 89.0 2.08 MB

Make your React Components aware of their width and height!

License: MIT License

JavaScript 95.45% TypeScript 4.55%
react react-component element-queries element-query utility

react-sizeme's Introduction

 

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].

react-sizeme's People

Contributors

adamchainz avatar alexanderanexsys avatar alzalabany avatar beckend avatar brodybits avatar chrisy-lili avatar coobaha avatar ctrlplusb avatar danawoodman avatar dependabot[bot] avatar felthy avatar greenkeeperio-bot avatar gregonarash avatar hdwatts avatar impzero avatar joeyjsonar avatar jongsue avatar jwoe avatar kaelxeth avatar lalnuo avatar monkeytacos avatar nnnaix avatar sanpochew avatar slig avatar tompradat avatar tonyxiao avatar tristanhessell avatar xaviervia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-sizeme's Issues

Figure out the SSR story

I have been attempting to implement support for SSR. So far, the only semi-working solution I could come up with involves avoiding calling createResizeDetector if the window object is undefined.

My fork is here lyuzashi@1242009

Doing so will prevent any errors, however components that are wrapped by SizeMe are not included in the server-side rendered HTML.

This appears to be due in part to the RenderWrapper, which is helpfully commented to be treaded on lightly.

By setting the initial state of both width and height in SizeAwareComponent to NaN, the wrapper is short circuited and the component renders without error on both the server and client.

This approach, however, does not pass the included tests – specifically any time the placeholder is expected to render before a size change occurs.

Other attempts at cracking this puzzle have caused checksum errors.

I am not entirely sure what the placeholder does. I'm fairly new to React but I get the feeling it's pretty important not to short-circuit it.

Any help would be greatly appreciated. I'd love to get SSR working with this component – it looks very handy! Sorry this is so detailed.

As a note, I chose to try NaN as the size for SSR, since it theoretically is a dimensionless environment but existing math code wont error out or evaluate in unexpected ways (due to casting), as it might with null. Not sure if that's the best idea, but it's what I came up with as a suggestion.

add "mapDimensionsToProps" option

Hi,

Current implementation seems great. However often our wrapped component will often use width / height to define "breakpoints" from which the component should render differently according to its size.

A problem with current implementation is that it injects width/height directly to wrapped component, so each time the dimensions changes, the wrapped component will generally re-render because of a props change. If the wrapped component is expensive to render it can be a problem.

It would really help if we had a "mapDimensionsToProps" option for the HOC.

The default would be retrocompatible with current behavior:

const sizeMeConfig = {
  monitorWidth: true,  
  monitorHeight: false, 
  refreshRate: 16,
  mapDimensionsToProps: dimensions => dimensions
};

but it would be possible to customize props passed to our wrapped component. For example imagine I want my wrapped component to customize itself when it is a perfect square, I don't need it to re-render on every dimensions changes. Just injecting it a boolean "isSquare" should be enough and would allow to prevent unnecessary renderings easily with shouldComponentUpdate.

const sizeMeConfig = {
  monitorWidth: true,  
  monitorHeight: false, 
  refreshRate: 16,
  mapDimensionsToProps: ({width,height}) => {isSquare: (width === height)}
};

I'm using this on my code and it works great
https://gist.github.com/slorber/27006e27997464c9f737ac22a8a89a94

Maintain the root element at all times.

I've been using react-sizeme to render an appropriate component based on the real estate available. One common pitfall with this use case is having your render switch out the root element completely.

For example:

class MySizedComponent extends Component {
   render() {
      const { size: { width } } = this.props;
      return width > 500
          ? <WideComponent />
          : <NarrowComponent />;
   }
}

Don't do this.

If you do you may get issues with the ref handler that react-sizeme uses to monitor your components dimensions with. Instead, always have a root element in your return that will never change.

For example:

class MySizedComponent extends Component {
   render() {
      const { size: { width } } = this.props;
      return (
         <div>
           {
             width > 500
               ? <WideComponent />
               : <NarrowComponent />
           }
        </div>
     );
   }
}

Note the wrapping div. Yes it's an extra DOM element, but it's semantically equivalent and now you get a nice dynamic component switcher outer.

Thought it worth sharing this. I'll add it to the docs, perhaps under the heading "common pitfalls".

Flex support

Hello, thanks for your awesome work!

I cannot make sizeme work with flex positioning. I'm tracking width and the size is updated only if component gets wider. If it becomes narrower, size does not change.

Optional clamping for reported width and height

Hey Sean,

Thanks a lot for your component – it saved me a couple of hours of life :–)

Not sure you would want to take this on board, but here is a thought that came to me when I was using Mapbox GL wrapped into react-sizeme. There was an issue when my container div shrunk to 0 – WebGL immediately threw a nasty error because the viewport had to be at least 1 px in size. Here is my workaround for this:

// MySuperMap = ...

// Do not allow width / height be 0
const sizeMeFix = (ComponentToWrap) => ({ size, ...rest }) => {
  const {
    width,
    height,
  } = size || {};

  const fixedSize = {
    width: isNumber(width) ? Math.max(width, 1) : width,
    height: isNumber(height) ? Math.max(height, 1) : height,
  };

  return <ComponentToWrap {...rest} size={fixedSize} />;
};

const MySizedSuperMap = sizeMe({
    monitorHeight: true,
    refreshRate: 200,
})(sizeMeFix(MySuperMap));

export default connect(mapStateToProps, mapDispatchToProps)(MySizedSuperMap);

So sizeMe is a wrapper for another wrapper called sizeMeFix, which makes sure that the wrapped component does not get incorrect numbers. I know I can fix the size right in the render() method of my component, but the size might be requested in a few other methods and this will create unwanted repetitions.

There might be other cases when reported width and height need to be clamped, so maybe having extra options like reportedMinWidth, reportedMaxWidth, reportedMinHeight, reportedMaxHeight can be a useful addition to your wrapper:

const MySizedSuperMap = sizeMe({
   monitorHeight: true,
   refreshRate: 200, 
   reportedMinHeight: 1,
   reportedMinWidth: 1,
})(MySuperMap);

What do you think?

Expose a reference to the wrapped component

It would be useful if we could access functions of the original component. It's an usual requirement, but it is a documented pattern.

I think the easiest way to achieve this is to make sure that the SizeMe container has a ref to the component passed into it. That way the parent of the SizeMe wrapper can call this.refs.wrapped.refs.original.doSomething().

nextProps and this.props always have the same size properties

I was originally trying to use react-component-queries but I noticed that my queries were only ever run once on first render, after then trying to implement my own version of it using shouldComponentUpdate and react-sizeme I ran into this issue which seems to be the root of my original problem. I'm not that good with Chrome Devtools but it seems that when strategisedSetState is called that is also somehow bypassing shouldComponentUpdate and mutating the props object. I have noPlaceholder set to true as we are using SSR, but apart from that am not doing anything out of the ordinary.

Any help with this would be appreciated.

NOTICE: Holiday'ing for 3 weeks.

Some much needed family quality time.

I'll be leaving the laptop at home.

I still care, I just won't be able to reply until the 26th.

x

Cannot read property 'onShrink' of undefined

I'm seeing the following error with version 2.4.2.

Uncaught TypeError: Cannot read property 'onShrink' of undefined
    at HTMLDivElement.onShrinkScroll (scroll.js:401)

This error seems to be related to this issue.

As mentioned in the comments, I downgraded to 2.4.1, after which the error went away.

Memory Leak

We use react-sizeme in a large application and resizeDetector stays in memory (it is a singleton). The result is that all react-sizeme children stay in memory and the retained memory from resizeDetector becomes larger and larger. We forked react-sizeme to create resizeDetector in the wrappedComponent so that resizeDetector is removed when the wrappedComponent is unmounted.

Do you have a reason to keep the resizeDetector as a singleton?

Cannot read property 'onExpand' of undefined

HI ,
I am using 2.4.2 version and getting following two errors

  1. Uncaught TypeError: Cannot read property 'onExpand' of undefined
    at HTMLDivElement.onExpandScroll (scroll.js:397)
  2. Uncaught TypeError: Cannot read property 'onShrink' of undefined
    at HTMLDivElement.onShrinkScroll (scroll.js:401)

there is one similar issue was already logged,but its status is closed.
So logging it again.

Position absolute on container div

Hi! It seems like wrapping a div in sizeMeHOC causes the outermost div to have a style: position='relative attribute to be attached. This conflicts in cases where we set the position via a class on the outermost div.

Here is a "pseudo" reproduction:

class Foo extends Component {
   render() {
     return <div className="absolute" />
   }
}

export default sizeMeHOC()(Foo);

Stabilise the demo

Not sure if the issue lies with the provider. May need to consider a stabler alternative.

Module not found: lodash/debounce and lodash/throttle

In kibana 6.2.2, I'm getting:

optmzr    log   [16:47:31.933] [fatal][optimize] Optimization failed in 2.09 secondsError: Optimizations failure.
   4192 modules
    
    ERROR in ./node_modules/react-sizeme/dist/react-sizeme.js
    Module not found: Error: Can't resolve 'lodash/debounce' in '/home/joey/Dev/sonark/node_modules/react-sizeme/dist'
    
    ERROR in ./node_modules/react-sizeme/dist/react-sizeme.js
    Module not found: Error: Can't resolve 'lodash/throttle' in '/home/joey/Dev/sonark/node_modules/react-sizeme/dist'

This was fixed if I went inside ./node_modules/react-sizeme/dist/react-sizeme.js and change the import of "lodash/debounce" and "lodash/throttle" to "lodash.debounce" and "lodash.throttle", respectively.

Size in readme

I was wondering whether the size of this lib, as reported in the readme, is still correct. For me, when only minified, this lib adds 148kB (when bundled separately, with webpack).

When testing the gzip compression with https://closure-compiler.appspot.com/home, I get the following gzip size:

Original Size:
44.6KB gzipped (144.64KB uncompressed)
Compiled Size:
39.17KB gzipped (108.37KB uncompressed)

Saved 12.17% off the gzipped size (25.08% without gzip)

So it compresses down to roughly 45kB gzipped. Now I'm assuming that the difference isn't just webpack bundling overhead. Do you know why my results are so different from the 9kB from the readme, am I overlooking something?

not re-rendering on redux

its not working with redux, the reducers are not re-rendering the component

I'm using the default configuration and any actions that i trigger on the container are only presented to the screen after a window resize.

Cannot read property 'width' of undefined

This always ends up happening at some point when I resize the window, and it stops sizeMe from working until the page is refreshed.

Uncaught TypeError: Cannot read property 'width' of undefined
    at finalizeDomMutation
    at Object.process
    at processBatch

Happens in

function finalizeDomMutation() {
  debug("finalizeDomMutation invoked.");

  if (!getState(element)) {
    debug("Aborting because element has been uninstalled");
    return;
  }

  var style = getState(element).style;
  storeCurrentSize(element, style.width, style.height);
  positionScrollbars(element, style.width, style.height);
}

Here is the result of getState(element):
image
So, yeah, style isn't there. Is there something I'm doing wrong?

invalid element-resize-detector dist file causes minification errors

react-sizeme depends on element-resize-detector and it currently fails minification with babili due to an error I reported over there: wnr/element-resize-detector#71

This was a bit painful to track down because the code is obfuscated.

This is a production show-stopper for me; hoping for a quick resolution over there because I'm unfamiliar with browserify. If someone here is familiar with browserify, I would think it's a quick fix. Once fixed, we'll need a new release of react-sizeme.

“failed to execute 'removeChild' on 'Node'” Exception

I'm getting the following exception in the issue fully described here (i can add details on request):

https://stackoverflow.com/questions/51408036/failed-to-execute-removechild-on-node-exception

scroll.js:639 Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

at Object.uninstall (webpack:///./node_modules/element-resize-detector/src/detection-strategy/scroll.js?:639:36)
at eval (webpack:///./node_modules/element-resize-detector/src/element-resize-detector.js?:300:31)
at utils.forEach (webpack:///./node_modules/element-resize-detector/src/collection-utils.js?:14:22)
at Object.uninstall (webpack:///./node_modules/element-resize-detector/src/element-resize-detector.js?:298:9)
at SizeAwareComponent.componentWillUnmount (webpack:///./node_modules/pnk-react-components/node_modules/react-sizeme/dist/react-sizeme.js?:371:27)
at callComponentWillUnmountWithTimer (webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:9687:14)
at HTMLUnknownElement.callCallback (webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:104:14)
at Object.invokeGuardedCallbackDev (webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:142:16)
at invokeGuardedCallback (webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:191:29)
at safelyCallComponentWillUnmount (webpack:///./node_modules/react-dom/cjs/react-dom.development.js?:9694:7)

Component is not rerenderd on resize

I am using the react-sizeme library to size my component like this:

import * as React from 'react';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { withSize, Size } from 'react-sizeme';

class MyComponent extends React.Component<MyProps>{
  render(){
    return <svg
      width="100%"
      height="100%"
      viewBox={`${-(this.props.size.width as number) / 2} ${-(this.props.size.height as number) / 2} ${this.props.size.width} ${this.props.size.height}`} 
      xmlns="http://www.w3.org/2000/svg"/>
  }
}

export default compose(
  withSize({ monitorHeight: true }),
  connect(mapStateToProps)
)(MyComponent);

It is working fine, except for the fact that the component is not rerendered when I resize the window. Any help would be greatly appreciated.

Components sized with react-sizeme disappear

(Closing since I can't reproduce this when trying the same code on another machine.)

This component seems to insert a bunch of DIV elements around its children, and one of them is being explicitly styled to have a width and height of zero. Any children inside a component created with sizeMe() will disappear from the screen.

In a file "ScaleDiv.jsx":

import React, { Component } from 'react';
import sizeMe from 'react-sizeme';

class ScaleDiv extends Component {
  render() {
    return (
      <div>{ this.props.children }</div>
    );
  }
}
const DecoratedScaleDiv = sizeMe({})(ScaleDiv);
export default DecoratedScaleDiv;

Then in a parent's render() method:

<ScaleDiv>HELLO</ScaleDiv>

"HELLO" disappears until I remove the call to sizeMe().

Proposal: add refreshDelayStrategy config option

Add refreshDelayStrategy config option, remove lodash dependency and recude a lib size.

import sizeMe from 'react-sizeme';
import debounce from 'debounce';

export default sizeMe({
  refreshDelayStrategy: (work) => debounce(work, 16),
});

We have a lot of dependencies in our projects. If each lib reduce size by few kb... its ~30*4=120Kb...

Element position tracking

First of all I want to say thanks for the great work, I love the idea! 👍

I thought to make similar thing, but found react-sizeme could be a pretty good fit in my case..

The question is: why not to add the position tracking also?.. I'm working on drag'n'drop example in react-layer-stack and I what I need is to track the actual positions and sizes of "dropzones". What do you think?

Support for debounce

Can you add support for debounce as an alternative to throttling? This can be useful for a smoother resize experience and reduced recalculation thrashing.

Pitfalls when using flex layouts

The behaviour of element-resize-detector causes a div to be injected which helps with tracking. Unfortunately this can break your flex layouts. To resolve you need to create a wrapping div around the flex layout div.

Decouple initial re-render onComponentDidMount delay from refreshRate

Hey it is me again with a feature request/proposal. I was positively surprised that react-sizeme comes with a refresh rate, as I need to debounce the re-rendering cause of heavy computations caused by some highcharts I use.

So I simply set the refreshRate to 300ms and it worked quite perfect for me. But than I figured out, that the first re-rendering after componentDidMount, which replaces the placeholder with the real content, took also 300ms to show up.

So it would be cool to decouple the Initial re-rendering from the refreshRate, to instantly show up the content when the componentDidMount().

What do you think. I would create a PR for that.

Cannot read property 'insertBefore' of null

As I work in an enterprise portal environment I have to deliver my React bundles in a quite unorthodox way.

I attach the Webpack build bundle to the window object. The output property of my Webpack config looks a little bit like this:

{
    libraryTarget: 'var',
    library: ['reactComponents', 'myStuff123']
}

I then pick up the component from the window object (e.g. window.reactComponents.myStuff123) and render the React component as such:

        ReactDOM.render(
                React.createElement(window.reactComponents.myStuff123),
                document.getElementById('UNIQUE_ID')
        );

However, as I add a package, which includes react-resizeme, to the window object I guess that it's immediately trying to set up some event listeners or such, because I get this error:

Uncaught TypeError: Cannot read property 'insertBefore' of null

Is there any way of postponing the execution until it's actually rendered?

Loading example

A full example of the HTML and loading mechanisms looks like this:

<!DOCTYPE html>
<html>
<head>
    <script src="react-0.14.8.min.js"></script>
    <script src="react-dom-0.14.8.min.js"></script>
    <script src="bundle.js"></script>
</head>
<body>

<div id="UNIQUE_ID"></div>

<script>
    (function(){
        ReactDOM.render(
                React.createElement(window.reactComponents.NamespacedReactComponent),
                document.getElementById('UNIQUE_ID')
        );
    })();
</script>
</body>
</html>

Need to call a function on a wrapped component

Hello,

Thanks for this product!

I have a component that I need to call a data refresh method on when it is unhidden from a view. Wrapping it in sizeme was great for helping it to size correctly, but now I can't access it to call the refresh because the object is now a resizeme thing, instead of the old component with the refresh function.

How can I send a message to the object inside sizeme?

PropType Validation fails

Hey, I tested your library and it works pretty good so far. Anyhow I get the following error on initialization:

sizeme-example.js:691 Warning: Failed propType: Required prop size.width was not specified in SizeMeRender. Check the render method of SizeAwareComponent

I checked the code and you set

SizeMeRender.propTypes = {
  ...
    size: PropTypes.shape({
      width: PropTypes.number.isRequired,
      height: PropTypes.number.isRequired,
    })
  };

but width and height are undefined in the first runs (which is pretty much the intended functionality).

bildschirmfoto 2016-04-15 um 11 20 17

Wouldn't it be better to change it to:

SizeMeRender.propTypes = {
  ...
    size: PropTypes.shape({
      width: PropTypes.number,
      height: PropTypes.number,
    }).isRequired
  };

This way you enforce the shape, but allow the props inside of the shape to be undefined?

Render props pattern usage

Have you ever considered having sizeMe work where you use a <SizeMe> component and it passes the size down as a prop? I think this method feels a bit more readable. ReactMotion does something like this.

<SizeMe monitorHeight>
    {size => <div>{size.width}, {size.height}</div>}
</SizeMe>

reliese of v2.4.2 break SSR

v2.4.1 is working without problem with SSR. v2.4.2 throws error window is undefined with SSR.

ReferenceError: window is not defined
    at module.exports (/home/anon/Github/nextjs/mobx/node_modules/element-resize-detector/src/reporter.js:21:18)
    at module.exports (/home/anon/Github/nextjs/mobx/node_modules/element-resize-detector/src/element-resize-detector.js:91:20)
    at createResizeDetector (/home/anon/Github/nextjs/mobx/node_modules/react-sizeme/src/resizeDetector.js:9:27)
    at resizeDetector (/home/anon/Github/nextjs/mobx/node_modules/react-sizeme/src/sizeMe.js:171:20)
    at Object.sizeMe (/home/anon/Github/nextjs/mobx/.next/dist/bundles/pages/webpack:/pages/index.js?f7ee:51:22)
    at __webpack_require__ (/home/anon/Github/nextjs/mobx/.next/dist/bundles/pages/webpack:/webpack/bootstrap 96d62891e60ba037ef65?3539:21:1)
    at Object.2 (/home/anon/Github/nextjs/mobx/.next/dist/bundles/pages/index.js:2885:18)
    at __webpack_require__ (/home/anon/Github/nextjs/mobx/.next/dist/bundles/pages/webpack:/webpack/bootstrap 96d62891e60ba037ef65?3539:21:1)
    at /home/anon/Github/nextjs/mobx/.next/dist/bundles/pages/webpack:/webpack/bootstrap 96d62891e60ba037ef65?3539:68:1
    at Object.<anonymous> (/home/anon/Github/nextjs/mobx/.next/dist/bundles/pages/index.js:73:10)
    at Module._compile (module.js:649:30)
    at Object.Module._extensions..js (module.js:660:10)
    at Module.load (module.js:561:32)
    at tryModuleLoad (module.js:501:12)
    at Function.Module._load (module.js:493:3)
    at Module.require (module.js:593:17)

errors is shown right after I wrap my component. first render goes with SSR. Previous version worked without problems.

Default monitorHeight to true?

Would it be more intuitive this way?

I was having trouble wondering why my size.height does not get updated only to figure out it is not monitored by default.

Thanks for this package.

Can't call setState (or forceUpdate) on an unmounted component.

I'm using this library for passing the width to child component like so.

<SizeMe>
  {
    ({ size }) => (
      <TemplateContent 
        file={selectedFile} 
        numPages={numPages} 
        pageNumber={pageNumber} 
        width={size.width}
      />
    )
  }
</SizeMe>

After re-sizing the dome for checking the responsive ness i'm getting this warnings a lot.

Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
    in Form (at index.js:117)
    in BuildLinkForm (at EmployeeNavbar.js:97)
    in div (created by Modal)
    in div (created by Modal)
    in div (created by Modal)
    in Modal (created by Modal__DefaultModal)
    in Modal__DefaultModal (at index.js:74)
    in Modal (at EmployeeNavbar.js:89)
    in div (created by EmployeeNavbar__LinksItemContainer)
    in EmployeeNavbar__LinksItemContainer (at EmployeeNavbar.js:88)
    in div (created by Toolbar)
    in Toolbar (created by EmployeeNavbar__ContentContainerForDesktop)
    in EmployeeNavbar__ContentContainerForDesktop (at EmployeeNavbar.js:421)

Please let us know how to handle this.

getComputedStyle passed undefined

When using the react-component-queries package I get the following error. The package works as expected but I'm getting an error I'd rather not have in my console.

image

If you look at the screenshot below, you can see that the Container element (which I'm assuming is the placeholder you use) doesn't have any children.

image

I only use the component query on the top level component. I've tried wrapping the component in another component and a few other things but to no avail. The only problem I can think of is that I'm using preact with React aliased to preact-compat.

If the isUnrendered function isn't necessary to the functionality of react-sizeMe, I'd like to make a PR adding a check for undefined before line 183 and console log a warning so others can know what's going wrong?

Typescript definitions

Could there be any typescript definitions?

Right now I made the following in my own code to create them, but it would be cool if they were on the package:

type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;

export interface SizeMeProps {
  size: {
    width: number | null;
    height: number | null;
  };
}

export interface SizeMeOptions {
  monitorWidth?: boolean;
  monitorHeight?: boolean;
  monitorPosition?: boolean;
  refreshRate?: number;
  refreshMode?: 'throttle' | 'debounce';
  noPlaceholder?: boolean;
}

type SizeMeFunction = (options?: SizeMeOptions) => <P extends SizeMeProps>(component: React.ComponentType<P>) => React.ComponentType<Omit<P, 'size'>>;

export const sizeMe: SizeMeFunction = require('react-sizeme');

The observer stops working when component content is replaced

The observer stops working when component content is replaced. This may be an issue especially with simple (e.g. text only) components.

My component looks like:

  render(): JSX.Element {
    return (
      <div className="ellipsis">{this.state.truncatedText}</div>
    );
  }

When state changes it will replace text and also remove .erd_scroll_detection_container element. There s error message and it makes it quite hard to debug. Simple solution is to wrap this.state.truncatedText in one more element e.g:

  render(): JSX.Element {
   return (
      <div className="ellipsis" ref="container">
        <span>{this.state.truncatedText}</span>
      </div>
    );
  }

I believe it's worth to add info about DOM modyfication in the readme.

Fix PropTypes deprecated Warning

When I try to use react-sizeme, it shows this warning in my console.
Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
So how can I fix it?
Here the code I implement.

class CassettePlayer extends Component {
}

import sizeMe from 'react-sizeme';
export default sizeMe()(CassettePlayer);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.