Skip to content

Commit

Permalink
perf(Library): Version 2.
Browse files Browse the repository at this point in the history
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);`
  • Loading branch information
ctrlplusb committed Apr 19, 2016
1 parent 283abba commit 24b49cd
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 37 deletions.
36 changes: 25 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div>My dimensions are {width}px by {height}px</div>
<div>My width is {width}px</div>
);
}
}

export default SizeMe()(MyComponent); // Wired up here!
// Wired up here!
export default SizeMe()(MyComponent);
```

## Usage and API Details
Expand All @@ -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.

Expand Down
5 changes: 4 additions & 1 deletion src/SizeMe.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
80 changes: 55 additions & 25 deletions test/SizeMe.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 } }) => <div>{width} x {height}</div>
);
const SizeAwareComponent = SizeMe()(() => <div></div>);

const mounted = mount(<SizeAwareComponent />);

Expand All @@ -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 } }) => <div>{width} x {height}</div>
);

Expand Down Expand Up @@ -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 } }) => <div>{width} x {height}</div>
);
const SizeAwareComponent = SizeMe()(() => <div></div>);

const mounted = mount(<SizeAwareComponent />);

Expand All @@ -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 } }) => <div>{width} x {height}</div>
);
const SizeAwareComponent = SizeMe()(() => <div></div>);

const mounted = mount(<SizeAwareComponent className={`foo`} />);

Expand All @@ -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 } }) => <div>{width} x {height}</div>
);
const SizeAwareComponent = SizeMe()(() => <div></div>);

const mounted = mount(<SizeAwareComponent style={{ height: `20px` }} />);

Expand All @@ -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 } }) => <div>{width} x {height}</div>
);
const SizeAwareComponent = SizeMe()(() => <div></div>);

const mounted = mount(
<SizeAwareComponent style={{ height: `20px` }} className={`foo`} />
Expand All @@ -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 } }) => <div>{width} x {height || `null`}</div>
);

const mounted = mount(<SizeAwareComponent />);

// 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 } }) => <div>{width || `null`} x {height}</div>
);

const mounted = mount(<SizeAwareComponent />);

// 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 } }) => <div>{width} x {height}</div>
);

Expand All @@ -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 <div>{width} x {height} & {otherProp}</div>;
}
Expand Down

0 comments on commit 24b49cd

Please sign in to comment.