Last active
November 20, 2020 10:59
-
-
Save giovanicascaes/64bff742eaea8dc4e63f5c6245813959 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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