提问者:小点点

React钩子:延迟加载中断是否使用LayoutEffect?


我的网络应用程序有一个顶部导航栏,可以改变高度。它被固定在屏幕的顶部,css位置:固定。要将页面内容移动到它下面,我有一个间隔div,它更新其高度以匹配标题的高度,并将其他内容向下推。

我正在更新我的应用程序以使用React挂钩。我有一个useLayoutEffect钩子,它检查导航栏的高度,并更新垫片的高度以匹配。根据React文档:

与组件didMount或组件didUpdate不同的是,使用use效果计划的效果不会阻止浏览器更新屏幕。这使您的应用程序感觉更响应。大多数效果不需要同步发生。在不常见的情况下,他们这样做(例如测量布局),有一个单独的useLayout效果钩子,其API与use效果相同。

我似乎发现,React惰性加载中断useLayoutEffect。这是一个代码沙盒:

https://codesandbox.io/s/5kqxynp564

导航栏隐藏了一个div,包含文本“如果你能看到这个USELAYOUTEFFECT正在工作”。当使用直接导入时,文本上方的div的大小与导航栏匹配,将文本向下推到导航栏下方,文本变得可见。使用React.lazy时,(AppBarHeader.js中的)useLayout效应无法工作。

延迟加载发生在应用程序中。js:

//LOADING <COUNTER/> THIS WAY WORKS
// import Counter from "./Counter";

//LAZY LOADING <COUNTER/> THIS WAY BREAKS useLayoutEffect
const CounterPromise = import("./Counter");
const Counter = React.lazy(() => CounterPromise);

我错过了什么?


共1个答案

匿名用户

对于暂挂中的某个组件执行useLayoutEffect的时间,这似乎是一个实际的错误,而其他组件是延迟加载的。如果AppBarHeader是延迟加载的,而Counter不是延迟加载的,那么它可以正常工作,但是如果Counter是延迟加载的,AppBarHeaderuseLayoutEffect在DOM中完全渲染之前执行(高度仍然为零)。

这个沙盒以一种非常黑客的方式“修复”了它,这有助于进一步演示正在发生的事情。

我在应用程序中添加了以下内容。js

  replaceRefHeader = () => {
    this.setState({ ref_header: React.createRef() });
  };

然后将其传递给计数器

<Counter replaceRefHeader={this.replaceRefHeader} history={routeProps.history} />

然后在计数器中:

const Counter = ({ replaceRefHeader }) => {
  useLayoutEffect(() => {
    replaceRefHeader();
  }, []);

然后我把[props.ref_header]放在AppBarHeaderuseLayoutEffect的依赖项数组中。

我并不是说这是你应该做的(尽管像这样的事情可以作为临时解决办法)。这只是为了更清楚地说明时间问题。

我在这里记录了一个新问题:https://github.com/facebook/react/issues/14869