React Hooks: Lazy Loading Breaks useLayoutEffect?

Posted

技术标签:

【中文标题】React Hooks: Lazy Loading Breaks useLayoutEffect?【英文标题】: 【发布时间】:2019-07-10 06:29:47 【问题描述】:

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

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

与 componentDidMount 或 componentDidUpdate 不同,使用 useEffect 安排的效果不会阻止浏览器更新屏幕。这使您的应用程序感觉更灵敏。大多数效果不需要同步发生。在不常见的情况下(例如测量布局),有一个单独的 useLayoutEffect Hook,其 API 与 useEffect 相同。

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

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

导航栏隐藏了一个 div,其中包含文本“如果您可以看到此 USELAYOUTEFFECT 正在工作”。使用直接导入时,该文本上方的 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);

我错过了什么?

【问题讨论】:

你能在这里发布一个最小的复制品吗? 当你发现一个错误时,请把它报告给 React repo。 @DanAbramov 我为此创建了一个问题。这个链接在我的回答中。 @DanAbramov 会的。 【参考方案1】:

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

This sandbox 以一种非常骇人听闻的方式“修复”它,这有助于进一步证明正在发生的事情。

我将以下内容添加到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

【讨论】:

以上是关于React Hooks: Lazy Loading Breaks useLayoutEffect?的主要内容,如果未能解决你的问题,请参考以下文章

React中异步模块api React.lazy和React.Suspense

@apollo/react-hooks 中的 `useSubscription` 方法加载卡住

将参数传递给 react-apollo-hooks useQuery

有没有办法使用 @apollo/react-hooks 访问多个 graphql 突变的选项

Angular Lazy Loading

javascript Lazy Loading de Requests com Axios