我知道这个问题已经被问过很多次了,答案总是当引用发生变化时,效果不会运行,但这不是问题,因为我每秒运行一次效果,直到我有一个具有高度的 html 元素。这是因为该元素稍后渲染并且高度为 0,直到用户填充我们的内容并单击按钮。
这是我正在使用的代码:
const [containerHeight, setContainerHeight] = useState(200);
const [checkCompnent, setCheckComponent] = useState(0);
useEffect(() => {
let clear = setTimeout(() => {
console.log(
'in timeout',
stickyContainerRef.current,
stickyContainerRef.current?.clientHeight,//allways logs 0
stickyContainerRef.current?.id
);
if (
stickyContainerRef.current &&
stickyContainerRef.current.clientHeight
) {
//never happens
console.log('setting height', stickyContainerRef.current.clientHeight);
setContainerHeight(stickyContainerRef.current.clientHeight);
} else {
console.log('retry');
setCheckComponent((c) => c + 1);
}
}, 1000);
return () => {
clearTimeout(clear);
};
}, [checkCompnent]);
<div id="whynotworky" ref={stickyContainerRef}>
效果每秒运行一次,但元素的高度永远不会超过 0,id 被正确记录为 Whynotworky,当我打开开发控制台并运行
document.getElementById("whynotworky").clientHeight
时,它会给我 2700。这几乎就像 React 设置 ref 但然后永远不会在以后的渲染中更新它。我很想放弃损坏的引用方式,只使用 document.getElementById 但我认为你不应该这样做。
我在 Firefox 中运行它,React 版本是 17.0.2
clientHeight
不是浏览器窗口的高度。它是 div 元素的高度。由于它没有文本(这将导致 div 至少具有 some 高度)并且高度不是通过 CSS 设置的,因此高度必须是 0
。这种行为是正确的。
来自MDN:
对于没有 CSS 或内联布局框的元素,
只读属性为零;否则,它是元素的内部高度(以像素为单位)。它包括填充,但不包括边框、边距和水平滚动条(如果存在)。Element.clientHeight