我的网络应用程序有一个顶部导航栏,可以改变高度。它被固定在屏幕的顶部,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);
我错过了什么?
对于暂挂
中的某个组件执行useLayoutEffect
的时间,这似乎是一个实际的错误,而其他组件是延迟加载的。如果AppBarHeader
是延迟加载的,而Counter
不是延迟加载的,那么它可以正常工作,但是如果Counter
是延迟加载的,AppBarHeader
的useLayoutEffect
在DOM中完全渲染之前执行(高度仍然为零)。
这个沙盒以一种非常黑客的方式“修复”了它,这有助于进一步演示正在发生的事情。
我在应用程序中添加了以下内容。js
:
replaceRefHeader = () => {
this.setState({ ref_header: React.createRef() });
};
然后将其传递给计数器
:
<Counter replaceRefHeader={this.replaceRefHeader} history={routeProps.history} />
然后在计数器
中:
const Counter = ({ replaceRefHeader }) => {
useLayoutEffect(() => {
replaceRefHeader();
}, []);
然后我把[props.ref_header]
放在AppBarHeader
的useLayoutEffect
的依赖项数组中。
我并不是说这是你应该做的(尽管像这样的事情可以作为临时解决办法)。这只是为了更清楚地说明时间问题。
我在这里记录了一个新问题:https://github.com/facebook/react/issues/14869