我想以一种可靠的方式找出DOM元素的尺寸.
I would like to find out the dimensions of a DOM element in a reliable way.
我的考虑是为此使用getBoundingClientRect.
My consideration was to use getBoundingClientRect for this.
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作出反应,而对rect更改不作出反应.显然,浏览器中组件的绘制尚未完成,因为尺寸始终为0.
The problem with this approach is that useEffect only reacts to elementRef.current and not to the rect changes. Apparently the drawing of the component in the browser is not finished yet, because the dimensions are always 0.
如果我在useEffect之外进行全部操作,那么它将起作用.在控制台中,我看到值为0的2倍值,然后是正确的尺寸.
If I do the whole thing outside the useEffect then it works. In the console I see 2 times values with 0 and then the correct dimensions.
具有useEffect:
With useEffect:
使用以外的效果:
但是,我想将尺寸保存为状态,为此,我需要useEffect.
However, I would like to save the dimensions in the state and for this I need the useEffect.
如何使用getBoundingClientRect实现此目的,或者还有另一种方法可以做到这一点?
How can I achieve this with getBoundingClientRect or is there another way to do this?
解决方案
这不是自我反应的问题.这是离子V5反应中的错误.
It was not a problem of react it self. It is a bug in ionic V5 react.
通常,您可以通过以下方式做到这一点:
Normally you can do it in this way:
reactjs/docs/hooks-faq.html#how-can-i-measure-a-dom-node
但这是一个问题:
github/ionic-team/ionic/issues/19770
我的解决方案是使用: github/que-etc/resize-observer-polyfill
My solution is to use: github/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]; } 推荐答案您可以使用callBackRef来实现所需的行为:
you can use a callBackRef to achieve desired behaviour:
import React, { useCallback, useState } from "react"; export default function App() { const [dimensions, setDimensions] = useState(null); const callBackRef = useCallback(domNode => { if (domNode) { setDimensions(domNode.getBoundingClientRect()); } }, []); return ( <div> <h1 ref={callBackRef}>Measure me</h1> </div> ); }`更多推荐
通过React中的getBoundingClientRect接收元素的尺寸
发布评论