React Native传递SVG图标作为Props时遭遇JSX类型错误
React Native传递SVG图标Props报错解决
问题描述
在React Native组件中尝试将SVG图标作为props传递时,遇到错误:
JSX element type 'Icon' does not have any construct or call signatures.
相关代码
子组件代码
type Props = { price: string; Icon: JSX.Element; }; const MapPin = ({ price, Icon }: Props) => ( <View style={styles.bubbleContainer}> <View style={styles.bubbleContent}> <Icon /> <Text style={styles.bubblePrice}>{price}</Text> </View> <View style={styles.bubbleArrow} /> </View> );
父组件代码
import BPIcon from '../../../../assets/images/maps/bp_icon.svg'; import ShellIcon from '../../../../assets/images/maps/shell_icon.svg'; import TescoIcon from '../../../../assets/images/maps/tesco_icon.svg'; import TexacoIcon from '../../../../assets/images/maps/texaco_icon.svg'; import sampleData from '../../sampleData'; const MapComponent = () => { const renderIcon = (type: string) => { switch (type) { case 'bp': return <BPIcon />; case 'shell': return <ShellIcon />; case 'texaco': return <TexacoIcon />; case 'tesco': return <TescoIcon />; } }; return ( <MapView ...> {sampleData.map((marker, i) => { console.log(marker.icon); const Icon = renderIcon(marker.icon); console.log(Icon); return ( <Marker key={i} coordinate={marker.coordinates}> <MapPin price={marker.price} Icon={Icon} /> </Marker> ); })} </MapView> ); };
示例数据代码
const sampleData = [ { name: 'test station', icon: 'shell', price: '15.00p', coordinates: { latitude: 52.56504897473243, longitude: -1.9835459043698045, }, }, { name: 'test station', icon: 'bp', price: '10.00p', coordinates: { latitude: 52.564655445785036, longitude: -1.9895132194946084, }, }, { name: 'test station', icon: 'texaco', price: '12.00p', coordinates: { latitude: 52.56675992926686, longitude: -1.9925531724706291, }, }, { name: 'test station', icon: 'tesco', price: '12.00p', coordinates: { latitude: 52.56464922306586, longitude: -1.9913983181615922, }, }, { name: 'test station', icon: 'texaco', price: '12.00p', coordinates: { latitude: 52.5653679624953, longitude: -1.9930410479235137, }, }, { name: 'test station', icon: 'shell', price: '12.00p', coordinates: { latitude: 52.563723048919684, longitude: -1.9902561905426908, }, }, ];
错误原因
你在子组件Props里把Icon定义为JSX.Element类型,这代表已经渲染完成的元素实例;但父组件传递的是<BPIcon />这类已创建的元素,子组件却试图把它当作可调用的组件使用(<Icon />)——两者逻辑矛盾,因此TypeScript抛出错误。
修复方案
两种可行方案任选其一:
方案一:直接传递已渲染元素,子组件直接渲染
适合不需要给图标传额外props的场景:
- 修改子组件的Props和使用方式:
type Props = { price: string; icon: JSX.Element; // 改名贴合语义,明确是元素而非组件 }; const MapPin = ({ price, icon }: Props) => ( <View style={styles.bubbleContainer}> <View style={styles.bubbleContent}> {icon} {/* 直接渲染元素,无需加括号 */} <Text style={styles.bubblePrice}>{price}</Text> </View> <View style={styles.bubbleArrow} /> </View> );
- 父组件传递时调整参数名:
// MapComponent中的map循环部分 {sampleData.map((marker, i) => { const icon = renderIcon(marker.icon); return ( <Marker key={i} coordinate={marker.coordinates}> <MapPin price={marker.price} icon={icon} /> </Marker> ); })}
方案二:传递组件本身,子组件调用渲染
更灵活,后续可方便给图标传size、color等props:
- 修改父组件的
renderIcon,返回组件而非已渲染元素:
const renderIcon = (type: string) => { switch (type) { case 'bp': return BPIcon; // 不要加<></>,直接返回组件本身 case 'shell': return ShellIcon; case 'texaco': return TexacoIcon; case 'tesco': return TescoIcon; default: return null; // 增加默认返回,避免undefined } };
- 修改子组件的Props类型,使用React的
ComponentType:
import type { ComponentType } from 'react'; type Props = { price: string; Icon: ComponentType; // 表示这是一个React组件类型 }; const MapPin = ({ price, Icon }: Props) => ( <View style={styles.bubbleContainer}> <View style={styles.bubbleContent}> <Icon /> {/* 现在可正常调用组件 */} <Text style={styles.bubblePrice}>{price}</Text> </View> <View style={styles.bubbleArrow} /> </View> );
- 父组件传递逻辑无需修改,保持
Icon={renderIcon(marker.icon)}即可。
内容的提问来源于stack exchange,提问作者Bomber
相关产品推荐
相关产品推荐

