React Suspense 延迟加载,无需回退

问题描述 投票:0回答:5

我想延迟加载我的组件,以减少我的初始包大小,并使用 React 路由器使用代码分割来动态获取组件。

但是,当使用 React Suspense 时,它们会强制您使用后备加载。
这是行不通的:

const lazyLoadComponent = Component =>
    props => (
        <Suspense> // Missing fallback property
            <Component {...props} />
        </Suspense>
    );

在我的例子中,我从服务器渲染 html,所以我不想使用微调器。
这会在我的屏幕上产生无用的闪烁! 即:

  • Html 加载
  • 出现占位符
  • 路线的PageComponent被加载
  • 我有自己的微调器,可以从页面组件中加载提要

在我的例子中,html 对应于加载的 React 组件。

是否有任何已知的 hack 可以轻松解决此问题(除了为复制 html (!!) 的任何路由创建加载程序,顺便说一句,这会使延迟加载变得无用)。

我对“强迫”我们添加加载程序有点不满意,而且我不明白强制执行这一决定背后的逻辑。

javascript reactjs react-router lazy-loading react-suspense
5个回答
8
投票

尝试在文档中使用代码分割

fallback
props 只是一个 React 元素,你可以将它设置为
null

const MyLazyComponent= React.lazy(() => import('./MyComponent'));

<Suspense fallback={null}>
    <MyLazyComponent />
</Suspense>

2
投票

我在 Github 上为此创建了一个问题:https://github.com/facebook/react/issues/19715

当前没有使用 React-Router / React 的干净解决方案。
然而,在使用并发模式的未来版本中可以预见到这一点。正如丹·阿布拉莫夫提到的:

关于您的具体功能要求,我想我可以重新构建它 略有不同。这并不是说你想要“可选的后备”,因为 这对于新屏幕来说没有意义(我们必须展示 某物)。我相信您正在寻找的是一种跳过显示的方法 如果内容已经是 HTML 格式,则后备。正是如此 React 在并发模式下运行,因此功能请求已经 实施(并最终成为默认行为 稳定发布)。

对我来说,等待不是问题,所以目前我将省略延迟加载路线,因为这涉及一个爱好项目,我有时间等待未来的版本。


2
投票

所以基本上我们要做的就是将加载器包装在组件中并使用该组件加载脚本(此处为可加载)。 这样我们就可以使用 React.lazy 而不使用任何动画。

由于我们的后备是空的,您将看不到任何动画,并且您的内容将始终可见。不会有内容隐藏的闪烁。

可加载.js

import React, { Suspense } from 'react';

const Loadable = (Component) => (props) => (
  <Suspense fallback={<></>}>
    <Component {...props} />
  </Suspense>
);

export default Loadable;

我们可以将导入包装在 Loadable 中,这样它就会延迟加载。 路线.js

import React, { lazy } from 'react';
import Loadable from './components/Loadable';

// page import
const Home = Loadable(lazy(() => import('./pages/home')));

// define routes
const routes = [
    {
        path: "dashboard",
        element: <Layout />,
        children: [
            {
                path: "",
                element: <Home />,
            },
        ]
    },
]

0
投票

根据我的经验(React 17),如果将 null 传递给后备参数,则不会发生闪烁。

我有一个呈现惰性组件的模态组件。

这是我的打字稿解决方案:

type LazyLoadHOC = {
   component: React.LazyExoticComponent<any>,
   fallback?: React.ComponentType | null,
   [x:string]: any
};

export const LazyLoad: React.FC<LazyLoadHOC> = ({
     component: Component, fallback = null, ...props
}) => {
  return (
    <React.Suspense fallback={fallback}>
        <Component {...props} />
    </React.Suspense>
  );
};

这是我的模态:

const AddressFormModel = React.lazy(() => import('@components/address/address-form-modal'));

<Modal show={isOpen} backdrop={'static'} dialogClassName='custom-modal'>
    <ModalBody>
       {view === 'ADDRESS-FORM' && <LazyLoad component={AddressFormModel} />}
    </ModalBody>
</Modal>

这将确保不会触发您的全局 React.Suspense。


0
投票

当我尝试打开配置为延迟加载的模态组件时,我也遇到了同样的闪烁问题。我通过使用 startTransition 解决了这个问题

import { startTransition } from 'react';

function ComponentA() {
  const [openModal, setOpenModal] = useState(false);

  const modalHandler = () => {
     startTransition(() => {
       setOpenModal(!openModal)
     });
  }
  
}

您可以使用下面的 React 文档找到有关此内容的更多详细信息。
https://react.dev/reference/react/Suspense#preventing-already-revealed-content-from-hiding

© www.soinside.com 2019 - 2024. All rights reserved.