I have seen that checking if a flex container has wrapped/overflowed with JS is a thing.
Q1. Is this a practice used in this way or are there better ways to do that? The implementation seemed very simple and you can sort of not care about sizes and simply check if the container has wrapped/overflowed to rearrange the content or hide/show elements.
fluent ui has the ResizeGroup component which sort of does that but I just wanted to have a simpler implementation for learning.
Q2. I was able to do it with ResizeObserver but I am wondering if there are easier ways to do that? In my example there are some nav-links and a bunch of menu-buttons first we check for the overflow in the nav-links, once that happens we add/show an extra button to the end of the menu-links, which makes the size of it bigger and we then account for that in the math, when then, the menu-links overflow we only show the search button and the hamburger button.
I put in a pic to try to illustrate better
Here is what I have done, anything that easier than that to follow will be very much appreciated.
const refNavLinks = React.useRef<HTMLDivElement>();
const refNavMenu = React.useRef<HTMLDivElement>();
const ref = React.useRef<HTMLDivElement>();
const imgRef = React.useRef<HTMLDivElement>();
const refW = React.useRef<any>(null);
const [wrappedNav, setWrappedNav] = React.useState({r:null,s:false, w:0});
const [wrappedMenu, setWrappedMenu] = React.useState({r:null,s:false, w:0})
React.useLayoutEffect(() => {
refW.current = {npw: refNavLinks.current.scrollWidth,
mpw:refNavMenu.current.scrollWidth}
return () => {
console.log('no cleanup')
};
}, []);
React.useEffect(() => {
const el = ref.current;
const resizeObserver = new ResizeObserver(debounce(() => {
const isNavOverflowing = refNavLinks.current.offsetWidth < refNavLinks.current.scrollWidth
|| refNavLinks.current.parentElement.clientWidth
- (imgRef.current.scrollWidth + Math.max(refW.current.mpw, refNavMenu.current.scrollWidth))
< refW.current.npw;
const isMenuOverflowing = refNavMenu.current.offsetWidth < refNavMenu.current.scrollWidth
|| refNavMenu.current.parentElement.clientWidth
- (imgRef.current.scrollWidth) < refW.current.mpw;
if (isNavOverflowing) {
refW.current = {...refW.current,
mpw:refNavMenu.current.scrollWidth > refW.current.mpw
? refNavMenu.current.scrollWidth
: refW.current.mpw}
setWrappedNav({...wrappedNav,s:true})
} else {
refW.current = {...refW.current,
mpw:refNavMenu.current.scrollWidth > refW.current.mpw
? refNavMenu.current.scrollWidth
: refW.current.mpw}
setWrappedNav({...wrappedNav,s:false})
}
if (isNavOverflowing && isMenuOverflowing) {
setWrappedMenu({...wrappedMenu,s:true})
} else {
setWrappedMenu({...wrappedMenu,s:false})
}
},500))
resizeObserver.observe(ref.current);
return () => {
resizeObserver.unobserve(el);
resizeObserver.disconnect();
};
}, [ref.current])