You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

问题分析与修复方案

核心错误点

  1. 导航结构完全错误:你把NavigationDone作为组件定义,但点击按钮时仅引用了组件函数(() => NavigationDone),既没有渲染它,也没有正确集成导航容器。当前根组件App.tsx未包含任何导航容器,这是导航失效的根本原因。
  2. 按钮 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 09:52:07