导入SVG至BottomTabNavigator时出现元素类型无效错误,如何解决?
问题描述
将SVG文件导入BottomTabNavigator时,出现以下渲染错误:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: number.
已安装react-native-svg和react-native-svg-transformer,并添加了index.d.ts文件,内容为declare module '*.svg';。
相关代码
src/components/BottomTabNavigator.tsx
import React, {FC} from 'react'; import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; import screens from '../screens/'; import {BottomTabNavigatorIcons} from '../assets'; const Tab = createBottomTabNavigator(); const bottomTabNavigatorOptions = [ { id: 'search', name: 'Search', component: screens.SearchScreen, icon: BottomTabNavigatorIcons.defaultIcon.searchIcon, }, { id: 'record', name: 'Record', component: screens.RecordScreen, icon: BottomTabNavigatorIcons.defaultIcon.recordIcon, }, { id: 'profile', name: 'Profile', component: screens.ProfileScreen, icon: BottomTabNavigatorIcons.defaultIcon.profileIcon, }, ]; export const BottomTabNavigator: FC = () => { return ( <> <Tab.Navigator screenOptions={{headerShown: false}}> {bottomTabNavigatorOptions.map(screen => ( <Tab.Screen key={screen.id} name={screen.name} component={screen.component} options={{ tabBarIcon: () => <screen.icon />, }} /> ))} </Tab.Navigator> </> ); };
src/assets/index.ts
import ProfileIcon from './bottom-navigation/profile.svg'; import RecordIcon from './bottom-navigation/record.svg'; import SearchIcon from './bottom-navigation/search.svg'; const BottomTabNavigatorIcons = { defaultIcon: { profileIcon: ProfileIcon, recordIcon: RecordIcon, searchIcon: SearchIcon, }, }; export {BottomTabNavigatorIcons};
调试信息
console.log(bottomTabNavigatorOptions)输出显示icon字段为数字:
[{"component": [Function SearchScreen], "icon": 3, "id": "search", "name": "Search"}, {"component": [Function RecordScreen], "icon": 2, "id": "record", "name": "Record"}, {"component": [Function ProfileScreen], "icon": 1, "id": "profile", "name": "Profile"}]
问题原因
- SVG转换器配置未生效:
icon字段输出数字,说明SVG文件未被正确转换为React组件,而是被当作静态资源(数字为资源ID)导入。 - 组件渲染语法错误:JSX要求组件名称必须以大写字母开头,
<screen.icon />的写法不符合规范,无法正确识别为组件。
解决步骤
步骤1:完善react-native-svg-transformer配置
修改项目的metro.config.js(或metro.config.ts),确保SVG转换器正确生效:
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); module.exports = mergeConfig(getDefaultConfig(__dirname), { transformer: { babelTransformerPath: require.resolve('react-native-svg-transformer'), }, resolver: { assetExts: getDefaultConfig(__dirname).resolver.assetExts.filter(ext => ext !== 'svg'), sourceExts: [...getDefaultConfig(__dirname).resolver.sourceExts, 'svg'], }, });
同时更新index.d.ts,让TypeScript正确识别SVG类型:
declare module '*.svg' { import React from 'react'; import { SvgProps } from 'react-native-svg'; const content: React.FC<SvgProps>; export default content; }
步骤2:修复Tab.Screen的组件渲染代码
将tabBarIcon中的动态组件渲染方式修改为符合JSX规范的写法:
options={{ tabBarIcon: () => { const Icon = screen.icon; return <Icon />; }, }}
或直接使用React.createElement:
options={{ tabBarIcon: () => React.createElement(screen.icon), }}
步骤3:重启Metro服务
修改配置后,必须重置缓存并重启Metro bundler:
npx react-native start --reset-cache
验证
重启服务后重新运行项目,console.log(bottomTabNavigatorOptions)中的icon字段应显示为[Function Component],此时TabBar的SVG图标可正常渲染,不会再出现类型错误。
内容的提问来源于stack exchange,提问作者alski
相关产品推荐
相关产品推荐

