【问题标题】:Is there a way to check if a lazy-loaded component (with React.Lazy) has finished loading?有没有办法检查延迟加载的组件(使用 React.Lazy)是否已完成加载?
【发布时间】:2020-10-15 06:59:59
【问题描述】:

我正在开发一个应用程序,如果下一页有任何尚未加载的延迟加载组件,我们希望延迟页面之间的转换。所以我想弄清楚是否有任何方法可以可靠地检查延迟加载的组件是否已经完成加载。

此解决方案有效,但在延迟加载的组件第一次尝试加载时 - 即如果它立即呈现,因为延迟加载的组件已经加载。

import React, {PropsWithChildren, useEffect} from 'react'

export default function SuspenseTrigger(props) {
  return (
    <React.Suspense fallback={
      <>
        {props.fallback}
        <Trigger onLoad={props.onLoad} onComplete={props.onComplete} />
      </>
    }>
      {props.children}
    </React.Suspense>
  )
}

function Trigger(props) {
  useEffect(() => {
    if (props.onLoad) {
      props.onLoad()
    }

    return () => {
      if (props.onComplete) {
        setTimeout(props.onComplete)
      }
    }
  }, [])

  return <></>
}

此组件在第一次加载时正确调用onLoadonComplete。但是,在随后的时间里,由于延迟加载的组件现在被缓存,子组件会立即呈现,并且 永远不会呈现回退,这意味着永远不会调用 onLoadonComplete p>

我尝试过的一件事是在 SuspenseTrigger 的正文中添加第二个 Trigger

function ensureLoadCompleteCalled() {
  onLoad()
  onComplete()
}

return (
  <React.Suspense fallback={/* same as before */}>
    {props.children}
    <Trigger onLoad={ensureLoadCompleteCalled} />
  </React.Suspense>
)

这是行不通的,因为 Suspense 的子元素会立即渲染,即使其他元素没有完全加载。 所以onLoadonComplete 会立即被调用,无论是否Suspense 是否已加载完毕。

为了解决这个问题,我还尝试了一些更高级的状态检查(code on PasteBin)。主要的困难是检查后备是否已经呈现,我无法弄清楚如何可靠地做到这一点。我试过在检查之前等待 100 毫秒,但由于某种原因,即使这样也不能可靠地工作。 useRef 或许可以?

有什么想法吗?

【问题讨论】:

  • 您能像这样为孩子添加第二个触发器吗? {props.children}&lt;Trigger onLoad={props.onComplete} /&gt;

标签: javascript reactjs react-hooks react-suspense react-lazy-load


【解决方案1】:

检查_status 会起作用吗?

const Uninitialized = -1;
const Pending = 0;
const Resolved = 1;
const Rejected = 2;

https://github.com/facebook/react/blob/master/packages/react/src/ReactLazy.js

【讨论】:

    【解决方案2】:

    您是否尝试将您的 {props.children} 包装在加载器功能组件上,然后使用布局效果执行 onComplete 功能?

    这只是一个原始的想法,但它可能会起作用......

    const Loader = ({ onLoad, onComplete, children }) => {
      if (onLoad) {
        onLoad();
      }
    
      useLayoutEffect(() => {
        if (onComplete) {
          onComplete();
        }
      }, []);
    
      return children;
    }
    
    <React.Suspense fallback={/* same as before */}>
        <Loader onLoad={onLoad} onComplete={onComplete}>
          {props.children}
        </Loader>
    </React.Suspense>
    

    【讨论】:

    • 我不断收到此警告:在渲染不同组件 (Loader) 时无法更新组件 (BaseRoutes)。要在 Loader 中找到错误的 setState() 调用,请按照 Switch (at BaseRoutes.js:74) 中 Suspense (at BaseRoutes.js:80) 中的 Loader (at BaseRoutes.js:81) 中所述的堆栈跟踪在 BaseRoutes(在 Layout.js:55) 在 Layout(在 App.js:21) 在 Router(由 BrowserRouter 创建) 在 BrowserRouter(在 App.js:20) 在 App(在 src/index.js:55)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 2017-02-07
    • 2017-08-26
    • 1970-01-01
    • 2015-02-13
    • 2012-01-07
    • 2018-06-15
    相关资源
    最近更新 更多