React Native(TypeScript)导航异常求助:按钮点击无响应或闪退
问题描述
我尝试在SplashScreen的按钮 onPress 事件触发时跳转到HomeScreen,实现方式是创建DisplayImage组件嵌入SplashScreen,再把SplashScreen引入App.tsx。但点击按钮后毫无反应,有时应用还会闪退。请问我的实现哪里出错了?是否必须在App.tsx中配置导航?
相关代码
DisplayImage.tsx
import {NavigationContainerProps} from '@react-navigation/native'; import React from 'react'; import { Image, ImageSourcePropType, StyleSheet, View, TouchableOpacity, Text, StyleProp, ViewStyle, } from 'react-native'; import {NavigationContainer} from '@react-navigation/native'; import {createNativeStackNavigator} from '@react-navigation/native-stack'; import HomeScreen from './Homescreen'; const Stack = createNativeStackNavigator(); // Removed unnecessary import of createNativeStackNavigator interface AppButtonProps { onPress: () => void; title: string; } const AppButton: React.FC<AppButtonProps> = ({onPress, title}) => ( <TouchableOpacity onPress={onPress} style={styles.appButtonContainer}> <Text style={styles.appButtonText}>{title}</Text> </TouchableOpacity> ); interface DisplayImageProps { source: ImageSourcePropType; style?: StyleProp<ViewStyle>; } const DisplayImage: React.FC<DisplayImageProps> = ({source, style}) => { return ( <View style={[styles.imageContainer, style]}> <Image source={source} style={styles.image} /> <View style={styles.spacer} /> <AppButton title="Hey there!" onPress={() => NavigationDone} /> </View> ); }; const NavigationDone: React.FC<NavigationContainerProps> = ({}) => { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> </Stack.Navigator> </NavigationContainer> ); }; const styles = StyleSheet.create({ imageContainer: { width: 150, height: 150, justifyContent: 'center', alignItems: 'center', marginHorizontal: 100, marginTop: 200, }, image: { width: '100%', height: '100%', resizeMode: 'cover', borderRadius: 10, }, appButtonContainer: { elevation: 8, backgroundColor: '#009688', borderRadius: 10, paddingVertical: 10, paddingHorizontal: 12, }, appButtonText: { fontSize: 18, color: '#fff', fontWeight: 'bold', alignSelf: 'center', textTransform: 'uppercase', }, spacer: { height: 50, }, }); export default DisplayImage;
SplashScreen.tsx
import React from 'react'; import DisplayImage from './DisplayImage'; const SplashScreen = () => { return <DisplayImage source={require('../images/cherry.png')} />; }; export default SplashScreen;
HomeScreen.tsx
import React from 'react'; import {Text, View} from 'react-native'; const HomeScreen = () => { return ( <View> <Text>Hello</Text> </View> ); }; export default HomeScreen;
App.tsx
import React from 'react'; import {SafeAreaView, StyleSheet} from 'react-native'; import SplashScreen from './src/screens/Splashscreen'; function App(): React.JSX.Element { return ( <SafeAreaView style={styles.safe}> <SplashScreen /> </SafeAreaView> ); } const styles = StyleSheet.create({ safe: { height: '100%', width: '100%', }, }); export default App;
问题分析与修复方案
核心错误点
- 导航结构完全错误:你把
NavigationDone作为组件定义,但点击按钮时仅引用了组件函数(() => NavigationDone),既没有渲染它,也没有正确集成导航容器。当前根组件App.tsx未包含任何导航容器,这是导航失效的根本原因。 - 按钮 onPress 逻辑无效:
onPress={() => NavigationDone}只是返回了组件函数,没有执行任何导航动作,也没有触发页面切换。
正确实现步骤
必须在App.tsx中配置导航容器,因为React Navigation要求所有需要导航的组件必须包裹在NavigationContainer内。以下是修复后的完整代码:
1. 修改 App.tsx,配置全局导航结构
import React from 'react'; import {SafeAreaView, StyleSheet} from 'react-native'; import {NavigationContainer} from '@react-navigation/native'; import {createNativeStackNavigator} from '@react-navigation/native-stack'; import SplashScreen from './src/screens/Splashscreen'; import HomeScreen from './src/screens/Homescreen'; const Stack = createNativeStackNavigator(); function App(): React.JSX.Element { return ( <SafeAreaView style={styles.safe}> <NavigationContainer> <Stack.Navigator initialRouteName="Splash"> <Stack.Screen name="Splash" component={SplashScreen} options={{headerShown: false}} /> <Stack.Screen name="Home" component={HomeScreen} /> </Stack.Navigator> </NavigationContainer> </SafeAreaView> ); } const styles = StyleSheet.create({ safe: { flex: 1, width: '100%', }, }); export default App;
2. 修改 DisplayImage.tsx,使用导航钩子实现跳转
移除多余的导航组件定义,通过useNavigation钩子获取导航实例完成页面跳转:
import React from 'react'; import { Image, ImageSourcePropType, StyleSheet, View, TouchableOpacity, Text, StyleProp, ViewStyle, } from 'react-native'; import {useNavigation} from '@react-navigation/native'; import {NativeStackNavigationProp} from '@react-navigation/native-stack'; // 定义导航参数类型,保证类型安全 type RootStackParamList = { Splash: undefined; Home: undefined; }; interface AppButtonProps { onPress: () => void; title: string; } const AppButton: React.FC<AppButtonProps> = ({onPress, title}) => ( <TouchableOpacity onPress={onPress} style={styles.appButtonContainer}> <Text style={styles.appButtonText}>{title}</Text> </TouchableOpacity> ); interface DisplayImageProps { source: ImageSourcePropType; style?: StyleProp<ViewStyle>; } const DisplayImage: React.FC<DisplayImageProps> = ({source, style}) => { // 获取导航实例 const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>(); const handleNavigateToHome = () => { navigation.navigate('Home'); }; return ( <View style={[styles.imageContainer, style]}> <Image source={source} style={styles.image} /> <View style={styles.spacer} /> <AppButton title="Hey there!" onPress={handleNavigateToHome} /> </View> ); }; const styles = StyleSheet.create({ imageContainer: { width: 150, height: 150, justifyContent: 'center', alignItems: 'center', marginHorizontal: 100, marginTop: 200, }, image: { width: '100%', height: '100%', resizeMode: 'cover', borderRadius: 10, }, appButtonContainer: { elevation: 8, backgroundColor: '#009688', borderRadius: 10, paddingVertical: 10, paddingHorizontal: 12, }, appButtonText: { fontSize: 18, color: '#fff', fontWeight: 'bold', alignSelf: 'center', textTransform: 'uppercase', }, spacer: { height: 50, }, }); export default DisplayImage;
3. SplashScreen.tsx 和 HomeScreen.tsx 无需修改,保持原样即可
关键说明
- 根组件必须配置导航容器:
NavigationContainer是React Navigation的核心容器,所有需要导航的组件都必须在它的包裹范围内,因此必须在App.tsx中完成配置。 - 使用
useNavigation钩子跳转:组件内部通过该钩子获取导航实例,调用navigate方法跳转到指定页面,这是React Navigation的标准用法。 - 类型安全配置:定义
RootStackParamList可以让导航跳转时获得类型提示,避免输入错误的页面名称。
内容的提问来源于stack exchange,提问作者Freya19
相关产品推荐
相关产品推荐

