如果该文件存在,则动态导入 React 组件,否则显示默认消息
Posted
技术标签:
【中文标题】如果该文件存在,则动态导入 React 组件,否则显示默认消息【英文标题】:dynamically import a React Component if that file exists, otherwise show a default message 【发布时间】:2019-04-18 23:06:48 【问题描述】:如果文件存在,我想有条件地导入 React 组件,如果不存在,则执行其他操作。例如显示默认视图或消息。
我试过了:
let Recipe;
try
Recipe = require(`docs/app/Recipes/$props.componentName`);
catch (e)
Recipe = () => <div>Not found</div>;
但是 linter 抱怨我不应该尝试动态地要求文件,而是使用字符串文字。
对于我想要实现的目标,是否有更简洁的方法?
【问题讨论】:
【参考方案1】:其实是有的。随着最近发布的 React v16.6.0 "lazy code splitting" 被引入。这就是它的工作原理,它与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>
);
要处理找不到组件的情况,您可以使用Error Boundaries。你可以像这样用它来包装你的组件:
<ErrorBoundary>
<Suspense fallback=<Spinner/>>
<Recipe />
</Suspense>
</ErrorBoundary>
最好直接在我上面链接的 react 文档上阅读更多相关信息。
【讨论】:
【参考方案2】:问题在于这种方法会破坏包优化并将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>
一个更简洁的方法来做到这一点并避免 linter 错误是有一个可能组件的映射:
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
可以根据需要进行验证。
【讨论】:
以上是关于如果该文件存在,则动态导入 React 组件,否则显示默认消息的主要内容,如果未能解决你的问题,请参考以下文章