【问题标题】:React Native functional components - Navigate between different screens, each on a separate .js fileReact Native 功能组件 - 在不同的屏幕之间导航,每个屏幕都在一个单独的 .js 文件上
【发布时间】:2021-10-25 01:05:57
【问题描述】:

在我的基于 功能组件 的 React Native 应用程序中,我想在不同的屏幕之间导航,每个屏幕都位于一个单独的 .js 文件中。我希望能够像这样导航多个层:

[Screen1.js] [Screen2.js] [Screen3.js] [Screen4.js]

出于某种原因,the examples 中的 the tutorial 将所有屏幕放在同一个 App.js 文件中,每个屏幕都作为自己独立的功能,我认为这是不寻常的开发人员行为。

我希望将导航堆栈放在单个 NavigationService.js 文件中,然后由每个 Screen#.js 文件导入。我怎么能实现这个? (我已经看到了几个关于此的 SO 答案,以及一些在线教程,但似乎大多数都实现了 class 组件而不是 functional。)

以下是我实现此环境的尝试,但是当我尝试导航到新屏幕时,我得到_NavigationService.default.navigate is not a function. (In '_NavigationService.default.navigate('Email')', '_NavigationService.default.navigate' is undefined)

NavigationService.js:

import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import EmailScreen from './Email';
import HomeScreen from './App';

const Stack = createNativeStackNavigator();
  
function NavigationService( navigation ) {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Camera" component={CameraScreen} />
        <Stack.Screen name="Email" component={EmailScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default {navigation, NavigationService};

App.js(主屏幕):

import * as React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { Button } from 'react-native-elements';
import NavigationService from './NavigationService';

function HomeScreen() {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'white' }}>
    <Button buttonStyle={styles.cameraButton} titleStyle={styles.buttonText}
    onPress={() => NavigationService.navigate('Email')}
    title="Email pics"
    />
    </View>
  );
}

const styles = StyleSheet.create({
  cameraButton: {
    backgroundColor: 'red',
  },
  buttonText: {
    fontSize: 24
  }
});

export default HomeScreen;

Email.js(EmailScreen):

import * as React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import RNSmtpMailer from 'react-native-smtp-mailer';

function EmailScreen() {

    return(
        <View>
            <Text>Test hi hi hi</Text>
        </View>
    )
}
export default EmailScreen;

【问题讨论】:

    标签: ios reactjs react-native react-navigation


    【解决方案1】:

    您不必在各个屏幕中导入您的NavigationService。 React Navigation 会处理这个问题并注入一个您可以使用的 navigation 属性。

    使用例如

    function HomeScreen({ navigation }) {
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'white' }}>
        <Button buttonStyle={styles.cameraButton} titleStyle={styles.buttonText}
        onPress={() => navigation.navigate('Email')}
        title="Email pics"
        />
        </View>
      );
    }
    

    您的NavigationService 只会在您的入口点中的某处用于呈现堆栈导航器,我建议重命名它以避免误解它可以作为服务传递。它只是应用程序层次结构中的一个组件,用于建立导航堆栈,React Navigation 确保堆栈屏幕获得必要的属性,例如 navigationroute(例如,从中获取导航参数)。

    因此,您也不必将navigation 属性传递给您的NavigationService

    Here 是一个很棒的教程,功能组件分布在多个文件中。

    【讨论】:

    • 对我来说这是一个令人困惑的新概念,({navigation}) 可以在不同的.js 文件中神奇地调用,而无需先导入NavigationService.js。谢谢你。我不知道这是可能的。 Discord 用户建议我将HomeScreen(props) 作为参数传递,然后执行props.navigation.navigate('Email')。他们都工作。是的,你链接的那个教程的标签在我工作日的 8 小时中有 6 小时被拉起。对于我简单的大脑来说,在我的项目中解析和实现基本信息太复杂了。 (这也是一个令人沮丧的想法,我什至不得不这样做)
    • React Navigation 将这个属性注入到你的屏幕中,它和你的NavigationService 不一样。 --- 两种提取属性的方式都是一样的,({ navigation }) 只是写起来容易一点。当您的组件需要prop1prop2 时,您还会发现经常使用({ prop1, prop2, ...remainingProps }) 之类的混合物,其余的只是简单地传递下来。
    • 我的NavigationService.js 中的某些东西正在将navigation 属性注入到我的整个应用程序中,我假设。无论是const Stack = createNativeStackNavigator()import { NavigationContainer } from '@react-navigation/native';import { createNativeStackNavigator } from '@react-navigation/native-stack'; 还是export default NavigationService其中一个必须是我项目的所有.js 文件中{navigation} 的全球可用性的触发因素,是吗?
    • 不是您的所有.js 文件,只是您声明的屏幕:&lt;Stack.Screen name="Email" component={EmailScreen} /&gt; - 请记住,您的EmailScreen 不会在此处立即呈现。组件只是作为属性传递,React Navigation 决定何时以及如何渲染它。当它这样做时,它只需添加自己的 navigation 对象作为提供所有精美导航功能的属性:return &lt;YourComponent navigation={reactNavigationsNavigationObject} /&gt;; - 现在您可以使用它了。 (注意:显然这过于简单了。)
    • 太酷了。这就说得通了!简单的解释对我有好处 :) 感谢您为 SO 树立了积极的榜样
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    • 2020-10-21
    • 1970-01-01
    • 2021-05-16
    相关资源
    最近更新 更多