From 24b49cdfb619406ee09262e3d403b3e2613ccc35 Mon Sep 17 00:00:00 2001 From: Sean Matheson Date: Tue, 19 Apr 2016 12:03:33 +0100 Subject: [PATCH] perf(Library): Version 2. Okay, sorry about this, but I have decided to release a breaking change. That being said I think it's unlikely to affect many people. I've realised that I may be causing some confusion by always providing width/height values even if you aren't monitoring one of the dimensions. If you mistakenly rely on a dimension that isn't being monitored this may lead to gremlins in your code. Therefore I have decided to provide `null` values for any dimension that is not being monitored. By default we only monitor width, therefore if you would like to get values for height change the configuration for your SizeMe HOC to: `SizeMe({ monitorHeight: true })(YourComponent);` BREAKING CHANGE: Okay, sorry about this, but I have decided to release a breaking change. That being said I think it's unlikely to affect many people. I've realised that I may be causing some confusion by always providing width/height values even if you aren't monitoring one of the dimensions. If you mistakenly rely on a dimension that isn't being monitored this may lead to gremlins in your code. Therefore I have decided to provide `null` values for any dimension that is not being monitored. By default we only monitor width, therefore if you would like to get values for height change the configuration for your SizeMe HOC to: `SizeMe({ monitorHeight: true })(YourComponent);` --- README.md | 36 +++++++++++++------- src/SizeMe.js | 5 ++- test/SizeMe.test.js | 80 +++++++++++++++++++++++++++++++-------------- 3 files changed, 84 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 8ca0dbc..7e6c594 100644 --- a/README.md +++ b/README.md @@ -35,16 +35,17 @@ import SizeMe from 'react-sizeme'; class MyComponent extends Component { render() { - // Receive width and height via "size" prop! - const { width, height } = this.props.size; + // We receive width and height via "size" prop! + const { width } = this.props.size; return ( -
My dimensions are {width}px by {height}px
+
My width is {width}px
); } } -export default SizeMe()(MyComponent); // Wired up here! +// Wired up here! +export default SizeMe()(MyComponent); ``` ## Usage and API Details @@ -65,19 +66,32 @@ You first have to pass the `SizeMe` function a configuration object. The entire ```javascript const SizeMeHOC = SizeMe({ - // If true any changes to `width` will result in a new `size` prop being - // passed to your Component. + // 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. + // If false, then any changes to your Components rendered width will NOT + // cause any recalculation of the "size" prop. Additionally any "size" prop + // that is passed into your Component will always have a `null` value + // for the "width" property. monitorWidth: true, - // If true any changes to `height` will result in a new `size` prop being - // passed to your Component. + // 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. + // If false, then any changes to your Components rendered height will NOT + // cause any recalculation of the "size" prop. Additionally any "size" prop + // that is passed into your Component will always have a `null` value + // for the "height" property. monitorHeight: false, - // The maximum speed, in milliseconds, at which size changes should be - // propogated to your Components. This should not be set to lower than 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. refreshRate: 16 }); ``` -__IMPORTANT__: We don't monitor height by default, so if you use the default settings and your component only changes in height it won't recieve an updated `size` prop. I figured that in most cases we care about the width only and it would be annoying if vertical text spanning kept throwing out updates. +__IMPORTANT__: We don't monitor height by default, so if you use the default settings and your component only changes in height it won't cause a recalculation of the `size` prop. I figured that in most cases we care about the width only and it would be annoying if vertical text spanning kept throwing out updates. + +__IMPORTANT__: If you aren't monitoring a specific dimension (width or height) you will be provided `null` values for the respective dimension. This is to avoid any possible misconfigured implementation whoopsies. __IMPORTANT__: `refreshRate` is set very low. If you are using this library in a manner where you expect loads of active changes to your components dimensions you may need to tweak this value to avoid browser spamming. diff --git a/src/SizeMe.js b/src/SizeMe.js index 14327d1..6d69e2a 100644 --- a/src/SizeMe.js +++ b/src/SizeMe.js @@ -172,7 +172,10 @@ function SizeMe(config = defaultConfig) { checkIfSizeChanged = throttle((el) => { const { width, height } = el.getBoundingClientRect(); - const next = { width, height }; + const next = { + width: monitorWidth ? width : null, + height: monitorHeight ? height : null + }; if (this.hasSizeChanged(this.state, next)) { this.setState(next); diff --git a/test/SizeMe.test.js b/test/SizeMe.test.js index b393e87..659c869 100644 --- a/test/SizeMe.test.js +++ b/test/SizeMe.test.js @@ -66,9 +66,7 @@ describeWithDOM(`Given the SizeMe library`, () => { describe(`And the resize detector`, () => { describe(`When mounting and unmounting the placeholder component`, () => { it(`Then the resizeDetector registration and deregistration should be called`, () => { - const SizeAwareComponent = SizeMe()( - ({ size: { width, height } }) =>
{width} x {height}
- ); + const SizeAwareComponent = SizeMe()(() =>
); const mounted = mount(); @@ -84,7 +82,7 @@ describeWithDOM(`Given the SizeMe library`, () => { describe(`When mounting and unmounting a size aware component`, () => { it(`Then the resizeDetector registration and deregistration should be called`, () => { - const SizeAwareComponent = SizeMe()( + const SizeAwareComponent = SizeMe({ monitorHeight: true })( ({ size: { width, height } }) =>
{width} x {height}
); @@ -123,9 +121,7 @@ describeWithDOM(`Given the SizeMe library`, () => { describe(`When rendering a size aware component`, () => { describe(`And no className or style has been provided`, () => { it(`Then it should render the default placeholder`, () => { - const SizeAwareComponent = SizeMe()( - ({ size: { width, height } }) =>
{width} x {height}
- ); + const SizeAwareComponent = SizeMe()(() =>
); const mounted = mount(); @@ -136,9 +132,7 @@ describeWithDOM(`Given the SizeMe library`, () => { describe(`And only a className has been provided`, () => { it(`Then it should render a placeholder with the className`, () => { - const SizeAwareComponent = SizeMe()( - ({ size: { width, height } }) =>
{width} x {height}
- ); + const SizeAwareComponent = SizeMe()(() =>
); const mounted = mount(); @@ -149,9 +143,7 @@ describeWithDOM(`Given the SizeMe library`, () => { describe(`And only a style has been provided`, () => { it(`Then it should render a placeholder with the style`, () => { - const SizeAwareComponent = SizeMe()( - ({ size: { width, height } }) =>
{width} x {height}
- ); + const SizeAwareComponent = SizeMe()(() =>
); const mounted = mount(); @@ -162,9 +154,7 @@ describeWithDOM(`Given the SizeMe library`, () => { describe(`And a className and style have been provided`, () => { it(`Then it should render a placeholder with both`, () => { - const SizeAwareComponent = SizeMe()( - ({ size: { width, height } }) =>
{width} x {height}
- ); + const SizeAwareComponent = SizeMe()(() =>
); const mounted = mount( @@ -175,11 +165,53 @@ describeWithDOM(`Given the SizeMe library`, () => { }); }); - describe(`And the size event has occurred`, () => { - it(`Then the actual size aware component should render`, () => { - const refreshRate = 30; + describe(`And the size event has occurred when only width is being monitored`, () => { + it(`Then expected sizes should be provided to the rendered component`, () => { + const SizeAwareComponent = SizeMe({ monitorWidth: true, monitorHeight: false })( + ({ size: { width, height } }) =>
{width} x {height || `null`}
+ ); + + const mounted = mount(); + + // Initial render should be as expected. + expect(mounted.html()).to.equal(placeholderHtml); + + // Get the callback for size changes. + const checkIfSizeChangedCallback = resizeDetectorMock.listenTo.args[0][1]; + checkIfSizeChangedCallback({ + getBoundingClientRect: () => ({ width: 100, height: 150 }) + }); + + // Update should have occurred immediately. + expect(mounted.text()).to.equal(`100 x null`); + }); + }); + + describe(`And the size event has occurred when only height is being monitored`, () => { + it(`Then expected sizes should be provided to the rendered component`, () => { + const SizeAwareComponent = SizeMe({ monitorWidth: false, monitorHeight: true })( + ({ size: { width, height } }) =>
{width || `null`} x {height}
+ ); + + const mounted = mount(); + + // Initial render should be as expected. + expect(mounted.html()).to.equal(placeholderHtml); + + // Get the callback for size changes. + const checkIfSizeChangedCallback = resizeDetectorMock.listenTo.args[0][1]; + checkIfSizeChangedCallback({ + getBoundingClientRect: () => ({ width: 100, height: 150 }) + }); - const SizeAwareComponent = SizeMe({ refreshRate })( + // Update should have occurred immediately. + expect(mounted.text()).to.equal(`null x 150`); + }); + }); + + describe(`And the size event has occurred when width and height are being monitored`, () => { + it(`Then expected sizes should be provided to the rendered component`, () => { + const SizeAwareComponent = SizeMe({ monitorWidth: true, monitorHeight: true })( ({ size: { width, height } }) =>
{width} x {height}
); @@ -191,19 +223,17 @@ describeWithDOM(`Given the SizeMe library`, () => { // Get the callback for size changes. const checkIfSizeChangedCallback = resizeDetectorMock.listenTo.args[0][1]; checkIfSizeChangedCallback({ - getBoundingClientRect: () => ({ width: 100, height: 100 }) + getBoundingClientRect: () => ({ width: 100, height: 150 }) }); // Update should have occurred immediately. - expect(mounted.text()).to.equal(`100 x 100`); + expect(mounted.text()).to.equal(`100 x 150`); }); }); describe(`And it receives new non-size props`, () => { it(`Then the new props should be passed into the component`, () => { - const refreshRate = 16; - - const SizeAwareComponent = SizeMe({ refreshRate })( + const SizeAwareComponent = SizeMe({ monitorHeight: true, monitorWidth: true })( function ({ size: { width, height }, otherProp }) { return
{width} x {height} & {otherProp}
; }