Skip to content

Instantly share code, notes, and snippets.

@stekhn
Created June 10, 2022 08:55
Show Gist options
  • Save stekhn/cc9a9250241ee47c2df3b257121a8846 to your computer and use it in GitHub Desktop.
Save stekhn/cc9a9250241ee47c2df3b257121a8846 to your computer and use it in GitHub Desktop.
React responsive wrapper component that passes its current width and height to child elements. Supports default values and aspect ratios.
import React, { useRef, useLayoutEffect, useState } from 'react';
interface ResponsiveWrapperProps {
defaultWidth?: number;
defaultHeight?: number;
fixedWidth?: number;
fixedHeight?: number;
heightRatio?: number;
}
export const ResponsiveWrapper: React.FC<ResponsiveWrapperProps> = ({
defaultWidth = 640,
defaultHeight = 380,
fixedWidth,
fixedHeight,
heightRatio,
children
}) => {
interface Dimensions {
width: number;
height: number;
}
const targetRef = useRef<HTMLDivElement>(null);
const [dimensions, setDimensions] = useState<Dimensions>({ width: defaultWidth, height: defaultHeight });
let timer: ReturnType<typeof setTimeout>;
const checkDimensions = () => {
if (targetRef.current) {
const newWidth = fixedWidth || targetRef.current.offsetWidth || defaultWidth;
const newHeight = heightRatio
? newWidth * heightRatio
: fixedHeight || targetRef.current.offsetHeight || defaultHeight;
setDimensions({
width: newWidth,
height: newHeight
});
}
};
useLayoutEffect(() => {
checkDimensions();
}, []);
window.addEventListener('resize', () => {
clearInterval(timer);
timer = setTimeout(checkDimensions, 100);
});
return (
<div ref={targetRef}>
{React.cloneElement(children as React.ReactElement<any>, {
width: dimensions.width,
height: dimensions.height
})}
</div>
);
};
// Usage
// <ResponsiveWrapper heightRatio="0.67" defaultWidth="600" defaultHeight="400">
// <Chart />
// </ResponsiveWrapper>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment