具有动态宽度(使用 useLayoutEffect 和 SSR)的剪裁 div 的 clientWidth 值不正确

clientWidth value not correct of clipped div with dynamic width (using useLayoutEffect and SSR)

我有一个 div (.inner),其宽度基于其内容。

.inner {
  display: inline-block;
  position: absolute;
}

这被其父级 (.clipper) 使用 overflow: hidden 剪裁:

.clipper {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}

我想要内部元素的完整非剪裁宽度,我这样做是这样的:

useLayoutEffect(() => {
  const { clientWidth: innerWidth } = innerRef.current;
  // work with innerWidth..

  }, []);

但是,innerWidthclientWidth 或边界框宽度都是 return 裁剪值(在本例中为 370)。

在 DOM 中检查它会显示它的实际宽度 (723)。

此外,在 Hot Module Reload 之后,控制台会记录一次所需的宽度..

谁能告诉我这是怎么回事?它与重新渲染有关,还是与 console.log 有关?

显示内容的大小是多少

如果你想知道实际显示的内容占多少space,包括填充但不包括边框、边距或滚动条,你想使用Element.clientWidthElement.clientHeight 属性

内容有多大

如果您需要知道内容的实际大小,无论当前有多少内容可见,您需要使用 Element.scrollWidthElement.scrollHeight

see the documentation on MDN 了解更多详情

我想通了。

事实证明,我错误的 clientWidth 值是由于初始的、未水化的 UI 和预期的 UI 不匹配造成的。

我认为这可以通过延迟加载我的组件来解决,直到客户端 JS 加载并混合组件之后,请参阅选项 2 here:

但是这没有用,所以我使用 setTimeout 介绍了一些技巧,并使用 useIsomorphicLayoutEffect 来抑制 useLayoutEffect SSR 警告(参见 here)。

超时后我收到正确的 DOM 值。

useIsomorphicLayoutEffect(() => {
  // Check for refs
  if (containerRef.current && innerRef.current) {
    setTimeout(() => {
      const { clientWidth: containerWidth } = containerRef.current;
      const { clientWidth: innerWidth } = innerRef.current;

      maxTransform.current = innerWidth - containerWidth;

      checkForBoundaries();
    }, 1000);
  }
}, [checkForBoundaries]);