Skip to content

Instantly share code, notes, and snippets.

@vincentriemer
Created December 4, 2017 20:15
Show Gist options
  • Save vincentriemer/25e04d9b81c217b0ec98950eb06bc10c to your computer and use it in GitHub Desktop.
Save vincentriemer/25e04d9b81c217b0ec98950eb06bc10c to your computer and use it in GitHub Desktop.
React Component prototype that provides element query functionality via ResizeObserver
// @flow
import * as React from "react";
import ResizeObserver from "resize-observer-polyfill";
import invariant from "invariant";
type Entry = {
+contentRect: {
+width: number,
+height: number
}
};
type ROProps = {
children: (width: number, height: number) => React.Node
};
type ROState = {
width: number,
height: number
};
export default class ResizeObservable extends React.Component<
ROProps,
ROState
> {
ro: ?ResizeObserver;
domElement: ?HTMLElement;
constructor(props: ROProps) {
super(props);
this.state = { width: 0, height: 0 };
}
componentDidMount() {
this.ro = new ResizeObserver(this.handleResize);
invariant(this.domElement, `No DOM element has been set by ref to observe`);
this.ro.observe(this.domElement);
}
componentWillUnmount() {
if (this.ro != null) {
this.ro.disconnect();
this.ro = null;
}
}
handleResize = (entries: $ReadOnlyArray<Entry>) => {
const { width, height } = entries[0].contentRect;
this.setState({ width, height });
};
handleRef = (elem: ?HTMLElement) => {
this.domElement = elem;
};
render() {
const { children, ...restProps } = this.props;
const { width, height } = this.state;
return (
<div {...restProps} ref={this.handleRef}>
{children(width, height)}
</div>
);
}
}
<ResizeObservable className="foo" style={{ flex: 1 }}> // should be able to style the container however you want (I personally use inline styles)
{(width) => {
if (width <= 300) {
return "This is small";
} else {
return "This is big";
}
}}
</ResizeObservable>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment