React Native自定义BottomTabCard组件props与navigation传递报错解决
React Native自定义BottomTabCard组件报错及导航问题解决
问题背景
我在React Native中开发了自定义BottomTabCard函数式组件,代码如下:
const BottomTabCard=({props,navigation})=> { const [isActive, setIsActive] = useState(''); return ( <View style={[ styles.container, {height: props.TabHeight, width: props.TabWidth}, ]}> <View style={{flexDirection: 'row'}}> <TouchableOpacity onPress={() => setIsActive('home')}> <Icons name="home" size={35} style={[ styles.iconHome, {color: isActive == 'home' ? 'green' : 'grey'}, ]} /> </TouchableOpacity> <TouchableOpacity onPress={() => setIsActive('shopping-cart')}> <Icons name="shopping-cart" size={35} style={[ styles.iconCart, {color: isActive == 'shopping-cart' ? 'green' : 'grey'}, ]} /> </TouchableOpacity> <TouchableOpacity onPress={() => setIsActive('search')}> <Icons name="search" size={35} style={[ styles.iconSearch, {color: isActive == 'search' ? 'green' : 'grey'}, ]} /> </TouchableOpacity> <TouchableOpacity onPress={() => setIsActive('person')}> <Icons name="person" size={35} style={[ styles.iconPerson, {color: isActive == 'person' ? 'green' : 'grey'}, ]} /> </TouchableOpacity> <TouchableOpacity onPress={() => setIsActive('credit-card'),{navigation.navigate(ROUTE_NAME.ORDER)}}> <Icons name="credit-card" size={35} style={[ styles.iconCard, {color: isActive == 'credit-card' ? 'green' : 'grey'}, ]} /> </TouchableOpacity> </View> </View> ); } export default BottomTabCard;
我希望点击credit-card图标时跳转到对应页面,但出现了报错,该组件在Login页面中被使用,Login页面包含其他卡片组件。
报错信息
TypeError: Cannot read property 'TabHeight' of undefined
错误栈信息:
This error is located at: in BottomTabCard (created by Login) in RCTView (created by View) in View (created by Login) in Login (created by SceneView) in StaticContainer in EnsureSingleNavigator (created by SceneView) in SceneView (created by SceneView) in RCTView (created by View) in View (created by DebugContainer) in DebugContainer (created by MaybeNestedStack) in MaybeNestedStack (created by SceneView) in RCTView (created by View) in View (created by SceneView) in RNSScreen (created by AnimatedComponent) in AnimatedComponent in AnimatedComponentWrapper (created by InnerScreen) in Suspender (created by Freeze) in Suspense (created by Freeze) in Freeze (created by DelayedFreeze) in DelayedFreeze (created by InnerScreen) in InnerScreen (created by Screen) in Screen (created by SceneView) in SceneView (created by NativeStackViewInner) in Suspender (created by Freeze) in Suspense (created by Freeze) in Freeze (created by DelayedFreeze) in DelayedFreeze (created by ScreenStack) in RNSScreenStack (created by ScreenStack) in ScreenStack (created by NativeStackViewInner) in NativeStackViewInner (created by NativeStackView) in RNCSafeAreaProvider (created by SafeAreaProvider) in SafeAreaProvider (created by SafeAreaInsetsContext) in SafeAreaProviderCompat (created by NativeStackView) in NativeStackView (created by NativeStackNavigator) in PreventRemoveProvider (created by NavigationContent) in NavigationContent in Unknown (created by NativeStackNavigator) in NativeStackNavigator (created by MyStack) in MyStack (created by Route) in EnsureSingleNavigator in BaseNavigationContainer in ThemeProvider in NavigationContainerInner (created by Route) in Route (created by App) in Provider (created by App) in App in RCTView (created by View) in View (created by AppContainer) in RCTView (created by View) in View (created by AppContainer) in AppContainer in behalal(RootComponent), js engine: hermes
疑问
- 是否可以在函数式组件中同时接收props和navigation?
- 如何解决上述报错?
解决方案
1. 关于函数式组件接收props和navigation的问题
当然可以同时接收,只是你的参数解构写法错误。React组件的参数本身就是props对象,navigation是父组件(比如Login页面)传入的其中一个属性,你需要正确解构这些属性。
2. 核心报错修复(参数解构错误)
原组件定义const BottomTabCard=({props,navigation})=>是错误的:
- 这种写法意味着你想从props对象里解构出名为
props和navigation的属性,但父组件实际传入的是TabHeight、TabWidth和navigation,并没有名为props的属性,导致props变量为undefined,访问props.TabHeight就会抛出错误。
修复方式二选一:
- 方式一:直接解构需要的属性
const BottomTabCard=({ TabHeight, TabWidth, navigation })=> { const [isActive, setIsActive] = useState(''); return ( <View style={[ styles.container, {height: TabHeight, width: TabWidth}, // 直接使用解构后的变量 ]}> {/* 其他代码不变 */} </View> ); }
- 方式二:用props接收所有属性,再单独提取navigation
const BottomTabCard=(props)=> { const { navigation } = props; const [isActive, setIsActive] = useState(''); return ( <View style={[ styles.container, {height: props.TabHeight, width: props.TabWidth}, // 用props访问属性 ]}> {/* 其他代码不变 */} </View> ); }
3. 导航点击事件修复
原代码中credit-card的点击事件语法错误:
// 错误写法:逗号运算符不能正确执行多个语句 onPress={() => setIsActive('credit-card'),{navigation.navigate(ROUTE_NAME.ORDER)}}
正确写法:用大括号包裹多个语句,按顺序执行:
<TouchableOpacity onPress={() => { setIsActive('credit-card'); navigation.navigate(ROUTE_NAME.ORDER); }}> {/* Icon代码不变 */} </TouchableOpacity>
4. 可选优化:简化重复代码
可以把所有tab项抽成数组,通过map渲染,减少冗余代码:
const BottomTabCard=({ TabHeight, TabWidth, navigation })=> { const [isActive, setIsActive] = useState(''); // 定义tab项数组 const tabItems = [ { key: 'home', iconName: 'home', styleKey: 'iconHome' }, { key: 'shopping-cart', iconName: 'shopping-cart', styleKey: 'iconCart' }, { key: 'search', iconName: 'search', styleKey: 'iconSearch' }, { key: 'person', iconName: 'person', styleKey: 'iconPerson' }, { key: 'credit-card', iconName: 'credit-card', styleKey: 'iconCard', route: ROUTE_NAME.ORDER }, ]; return ( <View style={[ styles.container, {height: TabHeight, width: TabWidth}, ]}> <View style={{flexDirection: 'row'}}> {tabItems.map(item => ( <TouchableOpacity key={item.key} onPress={() => { setIsActive(item.key); // 如果有路由则跳转 if (item.route) { navigation.navigate(item.route); } }} > <Icons name={item.iconName} size={35} style={[ styles[item.styleKey], {color: isActive === item.key ? 'green' : 'grey'}, ]} /> </TouchableOpacity> ))} </View> </View> ); }
内容的提问来源于stack exchange,提问作者Arya
相关产品推荐
相关产品推荐

