如何延迟同时加载多个组件

时间:2020-04-27 17:06:23

标签: javascript reactjs react-router lazy-loading

我有2个组件,我想使用类似

的延迟加载来加载所有组件
const A = lazy(() => import("../test/A")); 
const B = lazy(() => import("../test/B")); 

这将创建2个单独的包,并在需要时将其导入。

但是,我要创建一个捆绑包,当该捆绑包加载时,我应该能够使用上述两个组件。

我也不想创建包含上述两个组件的单个组件,因为我想为它们两个提供单独的路由

我试图做这样的事情 https://codesandbox.io/s/eager-raman-mdqzc?file=/src/App.js

可以请人解释一下这种功能是否可能,如果可以,那么我怎么做和做错了

3 个答案:

答案 0 :(得分:2)

从文档中

借助React.lazy函数,您可以将动态导入呈现为常规组件。

React.lazy采用必须调用动态import()的函数。这必须返回一个Promise,该解析为包含默认导出的包含React组件的模块。

然后,应该在Suspense组件内部呈现惰性组件,这使我们可以在等待惰性组件加载时显示一些后备内容(例如加载指示符)。

您可以将Suspense组件放置在惰性组件上方的任何位置。您甚至可以使用单个Suspense组件包装多个惰性组件。

因此,如果您想使用lazy()来包装模块,则必须具有一个组件作为模块的default属性。因此,它不允许您自动使用将命名导出作为组件的模块。 但是,您可以轻松做出将已命名的导出转换为默认导出的承诺,并将其包装为惰性:

// in comboModule.js:
export A from '../test/A'
export B from '../test/B'

// in the code that needs lazy modules
  const A = lazy(() => import('./comboModule').then((module) => ({default: module.A})))
  const B = lazy(() => import('./comboModule').then((module) => ({default: module.B})))

请注意,我们必须在传递给import的初始化函数内调用lazy,否则导入将立即开始。 lazy的部分好处是,您可以等到父组件呈现惰性组件后再进行加载。但是,import()应该缓存第一次导入的结果,并且只加载一次代码。

在初始化函数中,我们使用thenimport()的结果从类似Promise({A: <Component>, B: <Component>})的内容转换为懒惰期望的初始化函数:Promise({default: <Component>})

现在我们有两个惰性组件,它们都来自一个模块文件。

资源:

答案 1 :(得分:1)

您可以使用Suspense等待两者。有两个捆绑包,但是您可以等待加载它们两者

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/about" component={About}/>
      </Switch>
    </Suspense>
  </Router>
);

答案 2 :(得分:0)

我写了一个效用函数来概括@garrett-motzner 在他的回答中所说的内容:

import {lazy} from 'react';

export const multiLazy = moduleLoaderArray => {
  const promises = Promise.all(moduleLoaderArray.map(loader => loader()));
  return moduleLoaderArray.map((m, index) =>
    lazy(() => promises.then(results => results[index]))
  );
}

像这样的魅力:

const [A, B] = multiLazy([
  () => import("../test/A"),
  () => import("../test/B"),
]);

所以不需要创建中间组件文件(当然除了实用功能)

我选择这种语法是为了尽可能接近 React.lazy 语法,但如果喜欢和经常使用,可以修改它以获得 multiLazy(['../test/A', '../test/B'])