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

rub*_*ntd 3 javascript jsx reactjs eslint webpack

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

我尝试了这个:

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

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

是否有更清洁的方法来解决我要达到的目标?

Est*_*ask 6

问题在于这种方法会杀死捆绑软件优化,并且docs/app/Recipes/即使不使用捆绑包,也会将所有文件包含到捆绑软件中。

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

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

用作:

<React.Suspense fallback={'loading...'}><Recipe/></React.Suspense>
Run Code Online (Sandbox Code Playgroud)

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

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>;
Run Code Online (Sandbox Code Playgroud)

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


Fab*_*amp 5

事实上是有的。最近发布的 React v16.6.0引入了“惰性代码分割”。这就是它的工作原理,将它与reacts''suspense'一起使用是有意义的:

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

    function SomeComponent() {
      return (
        <Suspense fallback={<Spinner/>}>
          <Recipe />
        </Suspense>
      );
    }
Run Code Online (Sandbox Code Playgroud)

要处理找不到组件的情况,您可以使用Error Boundaries。你可以用它来包装你的组件,如下所示:

<ErrorBoundary>
  <Suspense fallback={<Spinner/>}>
    <Recipe />
  </Suspense>
</ErrorBoundary>
Run Code Online (Sandbox Code Playgroud)

最好直接在我上面链接的反应文档上阅读更多有关它的信息。