//useElementSize.tsx
import useResizeObserver from '@react-hook/resize-observer';
import { MutableRefObject, useLayoutEffect, useState } from 'react';
interface Size {
width: number;
height: number;
}
export default function useElementSize<T extends HTMLElement = HTMLDivElement>(
target: MutableRefObject<T | null>,
) {
const [size, setSize] = useState<Size>({
width: 0,
height: 0,
});
useLayoutEffect(() => {
target.current && setSize(target.current.getBoundingClientRect());
}, [target]);
useResizeObserver(target, (entry) => {
setSize(entry.contentRect);
});
return size;
}
//Other component
import { Box } from '@mui/material';
import clsx from 'clsx';
import { Fragment, useRef, useState } from 'react';
import { useInView } from 'react-intersection-observer';
import Config from '../../../../config';
import { ViewerMode } from '../../../../models';
import { ScannedPage } from '../../../../models/generated';
import useScrollNavigationStore from '../../../../stores/ScrollNavigationStore';
import style from './DocumentPage.module.scss';
import { Word } from '../../../ui';
import useSize from '@react-hook/size';
import useElementSize from '../../../../hooks/useElementSize';
type DocumentPageProps = {
docIndex: number;
docPageIndex: number;
viewerMode: ViewerMode;
scannedPage: ScannedPage;
selected?: boolean;
};
export const DocumentPage = ({
docIndex,
docPageIndex,
viewerMode,
scannedPage,
selected = false,
}: DocumentPageProps) => {
const documentPageSrc = `${Config.API_BASE_URL}/api/v1/core/file/${encodeURIComponent(
scannedPage.imagePath,
)}/lob/Personenversicherung`;
const [isLoading, setIsLoading] = useState(true);
const setSelectedIndexes = useScrollNavigationStore(
(state) => state.setSelectedIndexes,
);
const imgRef = useRef<HTMLImageElement>(null);
const { width, height } = useElementSize<HTMLImageElement>(imgRef);
const widthRatio = width / scannedPage.width;
const heightRatio = height / scannedPage.height;
const { ref, inView } = useInView({
triggerOnce: true,
rootMargin: '0px 0px 90% 0px',
threshold: 0.8,
});
return (
<Box
ref={ref}
component={'div'}
data-inview={inView}
alignItems={'center'}
justifyContent={'center'}
className={clsx(style.documentWrapper, {
[style.selected]: selected,
[style.loading]: isLoading,
})}
sx={{ minHeight: '200px' }}
onClick={() => handleClick([docIndex, docPageIndex], viewerMode)}
>
{inView ? (
<div style={{ position: 'relative' }}>
<img
ref={imgRef}
loading="lazy"
width={scannedPage.width}
height={scannedPage.height}
src={documentPageSrc}
alt="document"
placeholder="document"
draggable={false}
style={{ width: '100%', height: '100%', userSelect: 'none' }}
onLoad={() => handleImgLoad()}
aria-hidden="true"
/>
{viewerMode === ViewerMode.Viewer &&
scannedPage.scannedLineBoxes?.map((line, lineIndex) => {
return (
<Fragment key={`Line${lineIndex}`}>
{line.words?.map((word, wordIndex) => {
return (
<Box
key={`Line${lineIndex}-Word${wordIndex}`}
top={`${word.y * heightRatio}px`}
left={`${word.x * widthRatio}px`}
width={`${word.width * widthRatio}px`}
height={`${word.height * heightRatio}px`}
margin={0}
position={'absolute'}
color={'transparent'}
border={'1px solid red'}
>
<Word
height={`${word.height * heightRatio}px`}
lineHeight={`${word.height * heightRatio}px`}
>
{word.text}
</Word>
</Box>
);
})}
</Fragment>
);
})}
</div>
) : null}
</Box>
);
};
I'm not sure why but Resize observer is not triggering at all. I tried using useSize hook implemented from this lib but this also is not working. Can you pls help me somebody ? What can cause this issue ? When I use target.current in dependency array of useLayoutEffect the initial width and height get set but consecutive resizing doesn't trigger anything.
I'm not sure why but Resize observer is not triggering at all. I tried using useSize hook implemented from this lib but this also is not working. Can you pls help me somebody ? What can cause this issue ? When I use target.current in dependency array of useLayoutEffect the initial width and height get set but consecutive resizing doesn't trigger anything.