Skip to content

Instantly share code, notes, and snippets.

@giovanicascaes
Last active November 20, 2020 10:59
Show Gist options
  • Save giovanicascaes/64bff742eaea8dc4e63f5c6245813959 to your computer and use it in GitHub Desktop.
Save giovanicascaes/64bff742eaea8dc4e63f5c6245813959 to your computer and use it in GitHub Desktop.
import React, { useRef, useEffect } from "react";
// Checks if API is supported; otherwise imports pollyfill
const ResizeObserver =
window.ResizeObserver || require("resize-observer-polyfill");
// Defines observer behaviour to react to changes upon container dimensions
const observer = new ResizeObserver(function (entries) {
// Default breakpoints. This object's keys will be mapped to CSS classnames used to
// dinamically style the elements inside container
const defaultBreakpoints = {
SM: 384,
MD: 576,
LG: 768,
XL: 960,
};
// Iterate through each element that have had its dimensions changed. As the observer is
// globally created for performance reasons, several elements could be observed
entries.forEach(function (entry) {
// Checks if container has been assigned custom breakpoints through
// `data-breakpoints` attribute
const breakpoints = entry.target.dataset.breakpoints
? JSON.parse(entry.target.dataset.breakpoints)
: defaultBreakpoints;
// Adds the CSS class associetad to breakpoint according to container width
Object.keys(breakpoints).forEach(function (breakpoint) {
const minWidth = breakpoints[breakpoint];
if (entry.contentRect.width >= minWidth) {
entry.target.classList.add(breakpoint);
} else {
entry.target.classList.remove(breakpoint);
}
});
});
});
// React component
export default function ResponsiveContainer({ breakpoints, ...otherProps }) {
const ref = useRef();
useEffect(() => {
const element = ref.current;
// Starts observing container
observer.observe(element);
return () => {
// When umounting component removes the container from observed elements list
observer.unobserve(element);
};
}, []);
let props = otherProps;
// Convenience for breakpoints attribute
if (breakpoints) {
props = {
...props,
"data-breakpoints": JSON.stringify(breakpoints),
};
}
// The container. `data-observe-resizes` can be used to search for all
// observed elements
return <div {...props} data-observe-resizes ref={ref} />;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment