【发布时间】:2018-03-19 22:05:19
【问题描述】:
我正在构建一个可配置的 Avatar 组件,该组件根据我们想要组合的头像类型组成不同的头像特征组件。例如。海盗头像由 PegLeg 组件和 Parrot 组件组成。
最终目标是拥有一个具有所有特征的 const 映射:
const characteristicMapping = {
pegleg: PeglegComponent, // component needed in Pirate avatar
parrot: ParrotComponent, // component needed in Pirate avatar
wand: WandComponent, // not used in Pirate, but used in Wizard.
};
然后基于prop(特征数组)我们组成我们需要的特征,例如
// For Pirate avatar with Pirate char. set to default value
const Avatar = ({ avatarCharacteristics = ['pegleg', 'parrot'] }) => (
<div>
{avatarCharacteristics.map(c => characteristicsMapping[c]).map(
(AvatarComponent, i) => <AvatarComponent key={i} />)}
</div>
);
我的理解是,只要 AvatarComponent 的第一个字母大写,这应该可以工作,而且可以!
但是,根据 PeglegComponent 和 ParrotComponent 的导入方式,我似乎遇到了一些问题。
我正在使用一个名为 Easy Import 的 babel 包来处理包/命名空间。
当前 PeglegComponent/ParrotComponent(sep 文件)都有 Easy Import 包名称,例如:
// @package Components/Avatar/Characteristics/PeglegComponent
export default PeglegComponent;
// @package Components/Avatar/Characteristics/ParrotComponent
export default ParrotComponent;
从 Characteristics 向下的一个文件夹,我有一个 index.js 文件,它的布局:
// @package Components/Avatar
import PeglegComponent from 'Components/Avatar/Characteristics/PeglegComponent';
import ParrotComponent from 'Components/Avatar/Characteristics/ParrotComponent';
export default {};
export { PeglegComponent, ParrotComponent };
因此,组成 Avatar 组件中的导入看起来像这样:
import { PeglegComponent, ParrotComponent } from 'Components/Avatar';
const characteristicsMapping = {
pegleg: PeglegComponent, // component needed for Pirate Avatar
parrot: ParrotComponent, // component needed for Pirate Avatar
};
// For Pirate avatar with Pirate char. set to default value
const Avatar = ({ avatarCharacteristics = ['pegleg', 'parrot'] }) => (
<div>
{avatarCharacteristics.map(c => characteristicsMapping[c]).map(
(AvatarComponent, i) => <AvatarComponent key={i} />)}
</div>
);
在这种情况下,我得到了错误:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports
更重要的是,如果我 console.log characteristicsMapping 我得到 {pegleg: undefined, parrot: undefined}
因此,无论出于何种原因,导入都失败了。奇怪的是,这似乎只是一个动态组件名称问题。例如。如果我这样做,它会起作用,并且导入完全相同:
import { PeglegComponent, ParrotComponent } from 'Components/Avatar';
// For Pirate avatar with Pirate char. set to default value
const Avatar = () => (
<div>
<PeglegComponent />
<ParrotComponent />
</div>
);
起初我以为我根本无法动态组件名称,但该功能消失了,但后来我发现这可以工作。
import PeglegComponent from 'Components/Avatar/Characteristics/PeglegComponent';
import ParrotComponent from 'Components/Avatar/Characteristics/ParrotComponent';
const characteristicsMapping = {
pegleg: PeglegComponent, // component needed for Pirate Avatar
parrot: ParrotComponent, // component needed for Pirate Avatar
};
// For Pirate avatar with Pirate char. set to default value
const Avatar = ({ avatarCharacteristics = ['pegleg', 'parrot'] }) => (
<div>
{avatarCharacteristics.map(c => characteristicsMapping[c]).map(
(AvatarComponent, i) => <AvatarComponent key={i} />)}
</div>
);
另外,如果我在与 PeglegComponent/ParrotComponent 相同的文件夹中有一个 index.js 文件,然后从那里导入它就可以工作。
在Components/Avatar/Characteristics 中有一个 index.js,其中包含:
// @package Components/Avatar/Characteristics
import PeglegComponent from 'Components/Avatar/Characteristics/PeglegComponent';
import ParrotComponent from 'Components/Avatar/Characteristics/ParrotComponent';
export default {};
export { PeglegComponent, ParrotComponent };
然后这个工作:
import { PeglegComponent, ParrotComponent } from 'Components/Avatar/Characteristics';
const characteristicsMapping = {
pegleg: PeglegComponent, // component needed for Pirate avatar
parrot: ParrotComponent, // component needed for Parrot avatar
};
// For Pirate avatar with Pirate char. set to default value
const Avatar = ({ avatarCharacteristics = ['pegleg', 'parrot'] }) => (
<div>
{avatarCharacteristics.map(c => characteristicsMapping[c]).map(
(AvatarComponent, i) => <AvatarComponent key={i} />)}
</div>
);
如果我将特性的 index.js 中的内容导入 Avatar 的 index.js(上一个目录),则会再次失败。
所以我有一些变通方法来解决我的问题,但是从 Components/Avatar 导入我可以直接这样做似乎不一致,但是如果我尝试从对象映射构造一个组件数组,那么组件出现未定义。
想看看是否有人可以向我解释为什么.. 这是 JSX 问题、React 问题还是 Easy Import 问题?或者我对命名/默认导出如何工作的理解......?
【问题讨论】:
标签: javascript reactjs jsx