При каждом отображении родителя DynamicLoader
воссоздает LazyComponent
. React видит новый компонент (не тот же объект), отключает предыдущий и монтирует новый.
Чтобы решить эту проблему, используйте React.useMemo()
внутри DynamicLoader
для запоминания текущего LazyComponent
и воссоздайте его, только если props.component
действительно изменится:
const DynamicLoader = ({ component, parentUpdate }) => {
const LazyComponent = useMemo(() => React.lazy(() => import(component)), [
component
]);
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent parentUpdate={parentUpdate} />
</Suspense>
);
};
Песочница - чтобы продемонстрировать запомненный LazyComponent
, я передаю внешний update
компоненту HomeA
.
Поскольку useMemo()
кэширование не гарантировано (реакция может время от времени освобождать память), вы можете написать простое ленивое кэширование, используя Map
:
const componentsMap = new Map();
const getCachedLazy = component => {
if (componentsMap.has(component)) return componentsMap.get(component);
const Component = React.lazy(() => import(component));
componentsMap.set(component, Component);
return Component;
};
const DynamicLoader = ({ component, parentUpdate }) => {
const LazyComponent = getCachedLazy(component);
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent parentUpdate={parentUpdate} />
</Suspense>
);
};
Песочница