如果该文件存在,则动态导入React组件,否则显示默认消息

时间:2018-11-15 19:06:55

标签: javascript reactjs webpack jsx eslint

我想有条件地导入一个React组件,如果该文件存在并且不做其他事情。例如,显示默认视图或消息。

我尝试过:

let Recipe;
try {
  Recipe = require(`docs/app/Recipes/${props.componentName}`);
} catch (e) {
  Recipe = () => <div>Not found</div>;
}

但是,lint抱怨我不应该动态地要求一个文件,而应该使用字符串文字。

是否有一种更清洁的方法来实现我要达到的目标?

2 个答案:

答案 0 :(得分:5)

问题在于这种方法是,它会杀死包优化,并将docs/app/Recipes/中的所有文件都包含到包中,即使它们没有被使用。

一种更好的写方法是使用<React.Suspense>React.lazy

const Recipe = React.lazy(() =>
  import(`docs/app/Recipes/${props.componentName}`)
  .catch(() => ({ default: () => <div>Not found</div> }))
);

哪个用作:

<React.Suspense fallback={'loading...'}><Recipe/></React.Suspense>

一种更干净的方法来避免棉绒错误是要对可能的组件进行映射:

import Foo from 'docs/app/Recipes/Foo';
import Bar from 'docs/app/Recipes/Bar';
...

const componentsMap = { Foo, Bar };

...

const Recipe = componentsMap[props.componentName] || () => <div>Not found</div>;

在这种情况下,props.componentName可以根据需要进行验证。

答案 1 :(得分:2)

实际上有。在最近的React v16.6.0版本中,引入了“ lazy code splitting”。这就是它的工作方式,将它与reacts的“悬念”一起使用是很有意义的:

 import React, {lazy, Suspense} from 'react';
 const Recipe = lazy(() =>import(`./docs/app/Recipes/${props.componentName}`));

    function SomeComponent() {
      return (
        <Suspense fallback={<Spinner/>}>
          <Recipe />
        </Suspense>
      );
    }

要处理找不到组件的情况,可以使用Error Boundaries。您可以像这样包装您的组件:

<ErrorBoundary>
  <Suspense fallback={<Spinner/>}>
    <Recipe />
  </Suspense>
</ErrorBoundary>

最好让您直接从我上面链接的React文档中详细了解它。