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

时间:2020-06-24 22:14:12

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

我正在开发一个应用程序,如果下一页具有尚未加载的任何延迟加载的组件,我们希望在这些页面之间进行转换。因此,我试图找出是否有办法可靠地检查延迟加载的组件是否已经完成加载。

此解决方案有效,但仅在第一次 时才加载延迟加载的组件,也就是说,由于延迟加载的组件已经加载,因此无法立即呈现。

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

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

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

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

这是行不通的,因为Suspense的子代即使在其他元素未完全加载时也会立即呈现。所以onLoadonComplete不管悬念是否已完成加载,都会立即调用。

为解决此问题,我还尝试了一些更高级的状态检查(code on PasteBin)。最主要的困难是检查是否已提供回退,我无法弄清楚如何可靠地进行回退。我尝试在检查之前等待100毫秒,但由于某种原因,即使这样也无法正常工作。也许useRef可能吗?

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

您是否尝试将 {props.children} 包装在 Loader 功能组件上,以便在 useLayoutEffect 上执行 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>

答案 1 :(得分:0)

检查 _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