我想有条件地导入一个React组件,如果该文件存在并且不做其他事情。例如,显示默认视图或消息。
我尝试过:
let Recipe;
try {
Recipe = require(`docs/app/Recipes/${props.componentName}`);
} catch (e) {
Recipe = () => <div>Not found</div>;
}
但是,lint抱怨我不应该动态地要求一个文件,而应该使用字符串文字。
是否有一种更清洁的方法来实现我要达到的目标?
答案 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文档中详细了解它。