Есть ли способ проверить, завершила ли загрузка отложенный компонент (с React.Lazy)?

Я работаю над приложением, в котором у нас есть переходы между страницами, которые мы хотим отложить, если на следующей странице есть какие-либо компоненты с отложенной загрузкой, которые еще не были загружены. Итак, я пытаюсь выяснить, есть ли способ надежно проверить, не завершил ли загруженный компонент с отложенной загрузкой.

Это решение работает, но только в первый раз, когда компонент с отложенной загрузкой пытается загрузиться, т. Е. Не в том случае, если он отрисовывается мгновенно, потому что компонент с отложенной загрузкой уже загружен.

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первый раз загружается. Однако в последующие разы, так как компонент с отложенной загрузкой теперь кэшируется, дочерние элементы отображаются мгновенно, а резервный вариант никогда не отображается, что означаетonLoad а также onComplete никогда не звонят.

Одна вещь, которую я пробовал, это поставить вторую Trigger внутри тела SuspenseTrigger:

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

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

Это не работает, потому что дети Suspenseотображаются мгновенно, даже если другие элементы загружены не полностью. ТакonLoad а также onComplete вызывается мгновенно, независимо от того, завершена ли загрузка Suspense или нет.

Чтобы обойти это, я также попробовал более интересную проверку состояния (код на PasteBin). Основная сложная задача - проверить, был ли отрендерен резервный вариант, что я не могу понять, как это сделать надежно. Я пробовал подождать 100 мс перед проверкой, но даже это по какой-то причине не работает надежно. Может быть, это возможно сuseRef?

Есть идеи?

2 ответа

Вы пытались обернуть свой {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>

Будет ли проверять _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

Другие вопросы по тегам