React Native BottomTabBar内组件跳转新页面并传参问题
React Native 导航跳转与参数传递解决方案
问题场景
当前项目基于@react-navigation/bottom-tabs实现底部导航,ListScreen内部又嵌套了顶部Tab导航。需要在AllScreen组件中完成两个跳转需求:
- 点击右侧箭头图标跳转到
DetailsScreen,同时传递provincia参数 - 点击
CardResturant卡片跳转到餐厅详情页,传递对应餐厅信息参数
现有代码结构
App.js 底部导航配置
const Navigator = ()=> { return( <NavigationContainer> <Tab.Navigator initialRouteName={homeName} > <Tab.Screen name={homeName} component={HomeScreen} options={{ headerShown: false, tabBarIcon:()=>(<Icon name="home" size={25}/>)}}/> <Tab.Screen name={listName} component={ListScreen} options={{headerShown: false, tabBarIcon:()=>(<Icon name="list" size={20}/>)}}/> <Tab.Screen name={perizieName} component={PeritiScreen} options={{ headerShown: false, tabBarIcon:()=>(<Icon name="laptop" size={25}/>) }}/> </Tab.Navigator> </NavigationContainer> ); }
ListScreen 内部嵌套顶部Tab
const ListScreen = ()=>{ return( <SafeAreaView style={{flex:1}}> <Tab.Navigator swipeEnabled={false} initialRouteName="Lista completa" style={style.topTap} > <Tab.Screen name="Mappa" component={MapScreen} /> <Tab.Screen name="Lista completa" component={AllScreen} /> {/* 跳转逻辑所在组件 */} </Tab.Navigator> </SafeAreaView> ); };
AllScreen 待修改组件
<SafeAreaView> <View style={style.searchContainer}> <Text style={{paddingLeft:10}}> <Icon name="search" size={25} color={COLORS.grey} /> </Text> <TextInput placeholder="Cerca provincia" style={{fontSize:20, paddingLeft:10}} /> </View> <ScrollView> { masterList.map((provincia)=>{ return( <View> <View style={{flexDirection:"row"}}> <View> <Text style={style.provincia}> {provincia.nome} </Text> <Text style={{marginLeft:10, fontSize: 12, color:COLORS.grey, marginBottom:5}}>Ristoranti consigliati nella provincia di {provincia.nome},{"\n"}selezione quello che preferisci</Text> </View> <View style={{alignSelf:"center", alignItems:"center", paddingLeft: "18%"}}> <Icon onPress={"i need to go to DetailsScreen"} {/* 需修改此处 */} name="arrow-right" size={20} /> </View> </View> <ScrollView horizontal={true} showsHorizontalScrollIndicator={false} > { provincia.ristoranti.map((ristorante)=>{ return( <CardResturant resturant = {ristorante} /> {/* 需给卡片添加跳转 */} ) }) } </ScrollView> </View> )}) } </ScrollView> </SafeAreaView>
分步解决方案
1. 调整嵌套导航结构
因为要实现页面跳转,需要将ListScreen的内部Tab导航包裹在StackNavigator中,确保跳转路径存在:
import { createStackNavigator } from '@react-navigation/stack'; const Stack = createStackNavigator(); // 原Tab导航抽离为独立组件 const ListTabNavigator = () => { return( <Tab.Navigator swipeEnabled={false} initialRouteName="Lista completa" style={style.topTap} > <Tab.Screen name="Mappa" component={MapScreen} /> <Tab.Screen name="Lista completa" component={AllScreen} /> </Tab.Navigator> ); }; // 修改ListScreen为栈嵌套Tab结构 const ListScreen = ()=>{ return( <Stack.Navigator> <Stack.Screen name="ListTab" component={ListTabNavigator} options={{headerShown: false}} /> <Stack.Screen name="DetailsScreen" component={DetailsScreen} /> <Stack.Screen name="RestaurantDetailScreen" component={RestaurantDetailScreen} /> </Stack.Navigator> ); };
2. 在AllScreen中实现跳转逻辑
导入useNavigation钩子,为箭头和卡片添加点击事件并传递参数:
import { useNavigation } from '@react-navigation/native'; const AllScreen = () => { const navigation = useNavigation(); return( <SafeAreaView> {/* 原有搜索栏代码 */} <ScrollView> { masterList.map((provincia)=>{ return( <View key={provincia.id}> {/* 必须添加唯一key */} <View style={{flexDirection:"row"}}> {/* 原有省份信息代码 */} <View style={{alignSelf:"center", alignItems:"center", paddingLeft: "18%"}}> <Icon onPress={() => { // 跳转到省份详情页并传参 navigation.navigate('DetailsScreen', { provincia }); }} name="arrow-right" size={20} /> </View> </View> <ScrollView horizontal={true} showsHorizontalScrollIndicator={false} > { provincia.ristoranti.map((ristorante)=>{ return( <CardResturant key={ristorante.id} resturant={ristorante} onPress={() => { // 跳转到餐厅详情页并传参 navigation.navigate('RestaurantDetailScreen', { ristorante }); }} /> ) }) } </ScrollView> </View> )}) } </ScrollView> </SafeAreaView> ); };
3. 修改CardResturant组件支持点击
确保卡片组件使用可点击容器包裹,并接收onPress回调:
import { TouchableOpacity } from 'react-native'; const CardResturant = ({ resturant, onPress }) => { return( <TouchableOpacity style={/* 你的卡片样式 */} onPress={onPress} > {/* 卡片内部内容:餐厅名称、图片等 */} <Text>{resturant.nome}</Text> {/* 其他卡片元素 */} </TouchableOpacity> ); };
4. 在详情页接收参数
使用useRoute钩子获取传递的参数:
import { useRoute } from '@react-navigation/native'; // 省份详情页 const DetailsScreen = () => { const route = useRoute(); const { provincia } = route.params; return( <SafeAreaView> <Text>省份详情:{provincia.nome}</Text> {/* 使用provincia数据渲染页面 */} </SafeAreaView> ); }; // 餐厅详情页 const RestaurantDetailScreen = () => { const route = useRoute(); const { ristorante } = route.params; return( <SafeAreaView> <Text>餐厅详情:{ristorante.nome}</Text> {/* 使用ristorante数据渲染页面 */} </SafeAreaView> ); };
关键注意事项
- 嵌套导航中,子导航的页面跳转必须依赖父级栈导航,因此必须用StackNavigator包裹内部Tab导航
- 所有列表渲染项必须添加唯一
key属性,避免React警告 - 卡片组件必须使用
TouchableOpacity/Pressable等可点击组件,才能响应点击事件
内容的提问来源于stack exchange,提问作者Tommaso Ceredi
相关产品推荐
相关产品推荐

