Есть ли способ проверить, завершила ли загрузка отложенный компонент (с 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