Javascript 是否可以使用typescript创建一个通用的反应列表组件?
我正在创建一个列表组件,该组件应该处理要列表的不同对象。但是我找不到渲染该项目的解决方案。 列表需要是通用的,因为我有许多不同的东西要列出,但可能没有办法,我需要创建不同的列表组件来处理每个对象 我得到这个错误:Javascript 是否可以使用typescript创建一个通用的反应列表组件?,javascript,reactjs,typescript,Javascript,Reactjs,Typescript,我正在创建一个列表组件,该组件应该处理要列表的不同对象。但是我找不到渲染该项目的解决方案。 列表需要是通用的,因为我有许多不同的东西要列出,但可能没有办法,我需要创建不同的列表组件来处理每个对象 我得到这个错误: Property 'name' does not exist on type 'string | PrivilegeConditionOperator | PrivilegeConditionElement | Privilege'. Property 'name' does no
Property 'name' does not exist on type 'string | PrivilegeConditionOperator | PrivilegeConditionElement | Privilege'.
Property 'name' does not exist on type 'string'.
代码如下:
const GetItem = (
item: string | PrivilegeConditionOperator | PrivilegeConditionElement | Privilege,
index: number
) => {
switch (typeof item) {
case typeof PrivilegeConditionElement:
return `PrivilegeContionElement ${index}`;
case typeof Privilege:
return `Privilege ${index}`;
case typeof PrivilegeCondition:
return `PrivilegeContion ${index}`;
case typeof PrivilegeConditionOperator:
return item.name; //<===============ERROR when doing this
default:
return item;
}
};
const List: FC<Props> = ({ handelRemove, itemsList }) => (
<ListWrapper>
<ul style={{ listStyleType: "none", padding: "0", margin: 0 }}>
{itemsList.map((item, index) => (
<DivWithToolTip
data-tooltip={item}
// eslint-disable-next-line react/no-array-index-key
key={index}
style={{
display: "flex",
justifyContent: "row",
alignContent: "center",
alignItems: "center",
}}>
<li style={{ marginTop: "10px" }}>{GetItem(item, index)}</li>
<PlusButton
style={{ marginTop: "10px" }}
{...{ addIcon: false }}
onClick={() => handelRemove(item)}
/>
</DivWithToolTip>
))}
</ul>
</ListWrapper>
);
interface IListProps {
handelRemove: (item: string | PrivilegeConditionOperator | PrivilegeConditionElement | Privilege) => void;
itemsList: Array<string | PrivilegeConditionOperator | PrivilegeConditionElement | Privilege>;
}
type Props = IListProps;
export default List;
const GetItem=(
项:字符串| PrivilegeConditionOperator | PrivilegeConditionElement | Privilege,
索引:编号
) => {
开关(项目类型){
PrivilegeConditionElement的案例类型:
返回`PrivilegeContionElement${index}`;
特权的案例类型:
返回`Privilege${index}`;
PrivilegeCondition的案例类型:
返回`PrivilegeContion${index}`;
PrivilegeConditionOperator的案例类型:
return item.name;//(
{itemsList.map((项,索引)=>(
- {GetItem(item,index)}
handelRemove(项目)}
/>
))}
);
接口进程{
handelRemove:(项:字符串| PrivilegeConditionOperator | PrivilegeConditionElement | Privilege)=>void;
itemsList:数组;
}
类型Props=IListProps;
导出默认列表;
我也尝试过这个,但同样的错误是:
<li style={{ marginTop: "10px" }}>{item.name && item}</li>
{item.name&&item}
您遇到的问题不是特定于react的问题,而是特定于TypeScript的问题,因为TypeScript编译器抱怨GetItem
函数中的某些内容不是特定于react的
假设PrivilegeConditionOperator
是一个类,而不是接口
或类型
,您可以使用if…else if…
语句代替switch和instanceof
代替typeof
,如下所示:
const GetItem = (
item: string | PrivilegeConditionOperator | PrivilegeConditionElement | Privilege,
index: number
) => {
if (item instanceof PrivilegeConditionElement)
return `PrivilegeContionElement ${index}`;
else if (item instanceof Privilege)
return `Privilege ${index}`;
else if (item instanceof PrivilegeCondition)
return `PrivilegeContion ${index}`;
else if (item instanceof PrivilegeConditionOperator)
return item.name;
else
return item;
};
拯救通用组件。通过使用通用方法,您实际上可以简化并制作出更广泛使用的组件
这里的问题是,您正在传入一组不同的类型,但是您的getItem
函数是硬编码的。您应该传入适合所显示类型的getItem
函数
假设您按如下方式定义了道具界面:
interface IListProps<T> {
handleRemove: (item: T) => void;
itemsList: T[];
getItem: (v: T, index: number) => string; //pass this function into your component
}
因此,在同一个列表中,您可以同时渲染不同类型的项?即,并非一个特定渲染列表中的所有元素都属于同一类型?啊,instanceof完成了这个技巧,我只使用了if和no“if else”最后只使用了return。ESlint让我这么做:)。无论如何,谢谢你的帮助!该死的,这看起来很棒,我会试试的!
const List = <T,>({ handleRemove, itemsList, getItem }: React.PropsWithChildren<IListProps<T>>): JSX.Element => (
<ListWrapper>
<ul style={{ listStyleType: 'none', padding: '0', margin: 0 }}>
{itemsList.map((item, index) => (
<DivWithToolTip
data-tooltip={item}
// eslint-disable-next-line react/no-array-index-key
key={index}
style={{
display: 'flex',
justifyContent: 'row',
alignContent: 'center',
alignItems: 'center',
}}
>
<li style={{ marginTop: '10px' }}>{getItem(item, index)}</li>
<PlusButton
style={{ marginTop: '10px' }}
{...{ addIcon: false }}
onClick={() => handleRemove(item)}
/>
</DivWithToolTip>
))}
</ul>
</ListWrapper>
);
const [items,setItems] = React.useState([{name:"Christian"}]);
return <List
itemsList = {items}
handleRemove = {(item) => setItems(items.filter(v => v != item)}
getItem={(v, i) => `${v.name}`} />