Я хотел бы узнать размеры элемента DOM надежным способом.
Я хотел бы использовать для этого getBoundingClientRect.
const elementRef = useRef<HTMLUListElement | null>(null);
const [dimensions, setDimensions] = useState<DOMRect | undefined>();
const element: HTMLUListElement | null = elementRef.current;
/**
* Update dimensions state.
*/
const updateDimensions = useCallback(() => {
if (!element) return;
setDimensions(element.getBoundingClientRect());
}, [element, setDimensions]);
/**
* Effect hook to receive dimensions changes.
*/
useEffect(() => {
if (element) {
updateDimensions();
}
}, [element, updateDimensions]);
Проблема этого подхода заключается в том, что этот useEffect реагирует только на elementRef.current, а не на прямые изменения. Очевидно, что рисование компонента в браузере еще не закончено, потому что размеры всегда равны 0.
Если я делаю все это вне useEffect, то это работает. В консоли я вижу 2 раза значения с 0 и затем правильные размеры.
С useEffect:
![Dimensions with useEffect](https://i.stack.imgur.com/Cuhpq.png)
Вне использованияEffect:
![Dimensions outside useEffect](https://i.stack.imgur.com/ZLFXK.png)
Однако я хотел бы сохранить размеры в состоянии, и для этого мне нужно использовать useEffect.
Как я могу добиться этого с помощью getBoundingClientRect или есть другой способ сделать это?
РЕШЕНИЕ
Это не было проблемой, чтобы реагировать самостоятельно. Это ошибка в реакции ioni c V5.
Обычно вы можете сделать это следующим образом:
https://reactjs.org/docs/hooks-faq.html#how -can-i-measure-a-dom- узел
Но вот проблема:
https://github.com/ionic-team/ionic/issues/19770
Мое решение заключается в использовании: https://github.com/que-etc/resize-observer-polyfill
import { RefCallback, useCallback, useState } from 'react';
import ResizeObserver from 'resize-observer-polyfill';
export function useDimensions(): [RefCallback<HTMLElement | null>, DOMRect | undefined] {
const [dimensions, setDimensions] = useState<DOMRect | undefined>();
const ref: RefCallback<HTMLElement | null> = useCallback((node: HTMLElement | null) => {
if (node) {
setDimensions(node.getBoundingClientRect().toJSON());
const resizeObserver = new ResizeObserver((entries) => {
if (entries.length) {
setDimensions(entries[0].target.getBoundingClientRect().toJSON());
}
});
resizeObserver.observe(node);
return () => {
resizeObserver.unobserve(node);
resizeObserver.disconnect();
};
}
}, []);
return [ref, dimensions];
}