简体   繁体   English

有没有办法检查延迟加载的组件(使用 React.Lazy)是否已完成加载?

[英]Is there a way to check if a lazy-loaded component (with React.Lazy) has finished loading?

I'm working on an app where we have transitions between pages that we want to delay if the next page has any lazy-loaded components that haven't been loaded yet.我正在开发一个应用程序,如果下一页有任何尚未加载的延迟加载组件,我们希望延迟页面之间的转换。 So I'm trying to figure out if there's any way to reliably check whether a lazy-loaded component has finished loading yet.所以我试图弄清楚是否有任何方法可以可靠地检查延迟加载的组件是否已经完成加载。

This solution works, but only the first time the lazy-loaded component tries to load -- ie not if it renders instantly because the lazy-loaded component is already loaded.此解决方案有效,但在延迟加载的组件第一次尝试加载时才有效——即,如果它立即呈现,因为延迟加载的组件已加载。

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 <></>
}

This component correctly calls onLoad and onComplete the first time it's loaded.该组件在第一次加载时正确调用onLoadonComplete However, on subsequent times, because the lazy-loaded component is now cached, the children are rendered instantly and the fallback is never rendered, which means onLoad and onComplete never get called.但是,在随后的时间里,由于延迟加载的组件现在被缓存,子组件会立即渲染,并且永远不会渲染回退,这意味着永远不会调用onLoadonComplete

One thing I've tried is putting a second Trigger inside the body of the SuspenseTrigger :我尝试过的一件事是将第二个Trigger放在SuspenseTrigger的主体内:

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

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

That doesn't work because the children of Suspense get rendered instantly even when other elements aren't fully loaded.这不起作用,因为即使其他元素没有完全加载, Suspense的子元素也会立即呈现。 So onLoad and onComplete get called instantly, regardless of whether the Suspense is finished loading or not.所以onLoadonComplete会立即被调用,无论 Suspense 是否完成加载。

To get around that, I've also tried some fancier state-checking (code on PasteBin) .为了解决这个问题,我还尝试了一些更高级的状态检查(PasteBin 上的代码) The main tough thing there is checking whether the fallback has been rendered which I can't figure out how to reliably do.主要的困难是检查后备是否已经呈现,我无法弄清楚如何可靠地做到这一点。 I've tried waiting 100 ms before checking but even that doesn't work reliably for some reason.我试过在检查之前等待 100 毫秒,但由于某种原因,即使这样也不能可靠地工作。 Maybe it's possible with useRef ?也许使用useRef是可能的?

Any ideas?有任何想法吗?

have you try wrapping your {props.children} on a Loader Functional Component, so on useLayoutEffect yo execute the onComplete function?你有没有尝试将你的{props.children}包装在一个加载器功能组件上,所以在 useLayoutEffect 上执行 onComplete function?

Here just a raw idea, but it may work...这里只是一个原始的想法,但它可能会起作用......

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>

Would checking _status work?检查_status会起作用吗?

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM