8

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

该解决方案有效,但在延迟加载组件第一次尝试加载时才有效——即,如果它立即呈现,因为延迟加载组件已经加载,则不会。

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

该组件在第一次加载时onLoad正确调用。onComplete然而,在随后的时间里,因为延迟加载的组件现在被缓存了,孩子们被立即渲染并且永远不会渲染回退,这意味着永远不会被调用。onLoadonComplete

我尝试过的一件事是Trigger在主体内放一秒SuspenseTrigger

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

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

这不起作用,因为Suspense即使其他元素没有完全加载,子元素也会立即渲染。因此onLoadonComplete无论 Suspense 是否完成加载,都会立即被调用。

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

有任何想法吗?

4

2 回答 2

0

你有没有尝试将你的包装{props.children}在一个加载器功能组件上,所以在 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>
于 2021-01-21T15:25:23.547 回答
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

于 2021-07-01T18:55:19.913 回答