React Hooks:延迟加载中断 useLayoutEffect?

React Hooks: Lazy Loading Breaks useLayoutEffect?

我的网络应用程序有一个可以改变高度的顶部导航栏。它固定在屏幕顶部,css position: fixed。为了将页面内容移动到它下面,我有一个垫片 div,它更新它的高度以匹配 header 的高度,并将其他所有内容向下推。

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

Unlike componentDidMount or componentDidUpdate, effects scheduled with useEffect don’t block the browser from updating the screen. This makes your app feel more responsive. The majority of effects don’t need to happen synchronously. In the uncommon cases where they do (such as measuring the layout), there is a separate useLayoutEffect Hook with an API identical to useEffect.

我似乎发现,React 延迟加载会中断 useLayoutEffect。这是一个 CodeSandBox:

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

导航栏隐藏了一个 div,其中包含文本 "IF YOU CAN SEE THIS USELAYOUTEFFECT IS WORKING"。使用直接导入时,文本上方的 div 的大小与导航栏相匹配,将文本向下推到导航栏下方,并且文本变得可见。当使用React.lazy时,useLayoutEffect(在AppBarHeader.js中)失效。

延迟加载发生在 App.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);

我错过了什么?

看来这确实是 Suspense 中某个组件的 useLayoutEffect 执行时间的实际错误,其中一些其他组件是延迟加载的。如果 AppBarHeader 是延迟加载而 Counter 不是,它工作正常,但是对于 Counter 延迟加载,AppBarHeaderuseLayoutEffect 在完全呈现之前执行在DOM(高度仍然为零)。

This sandbox "fixes" 它以一种非常骇人听闻的方式帮助进一步演示正在发生的事情。

我在 App.js 中添加了以下内容:

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

然后将其传递给 Counter:

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

然后在Counter:

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

然后我将 [props.ref_header] 放入 AppBarHeaderuseLayoutEffect 的依赖数组中。

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

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