繁体   English   中英

如何在 React native 的父导航中导航到屏幕

[英]How to navigate to a screen in parent navigation in React native

我是 React Navigation 的新手,正在尝试在 react-native 中实现以下功能:我有一个堆栈导航器作为父级,底部导航栏作为其子级。 在主屏幕上,当用户单击注销选项时,他们应该返回到作为父导航一部分的登录屏幕。

已经有很多关于此的问题,但我无法在我的代码中实现以前的解决方案。

有人请帮助我,代码如下(这是一个 Expo 管理的项目):

导航组件

import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import WelcomeScreen from "../screens/WelcomeScreen";
import Features from "../screens/Features";
import SignIn from "../screens/SignIn";
import Register from "../screens/Register";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { Icon } from "react-native-elements";
import Home from "../screens/Home";
import Reminders from "../screens/Reminders";
import Settings from "../screens/Settings";

const BottomNavbar = () => {
    const Tab = createBottomTabNavigator();
    return (
        <Tab.Navigator
            initialRouteName="Home"
            screenOptions={({ route }) => ({
                tabBarIcon: ({ focused }) => {
                    let iconName;
                    let rn = route.name;
                    if (rn === "Home") {
                        iconName = focused ? "home" : "home-outline";
                    } else if (rn === "Reminders") {
                        iconName = focused ? "list" : "list-outline";
                    } else if (rn === "Settings") {
                        iconName = focused ? "settings" : "settings-outline";
                    }
                    return (
                        <Icon
                            name={iconName}
                            size={25}
                            color="black"
                            type="ionicon"
                        />
                    );
                },
            })}
            showLabel
        >
            <Tab.Screen
                name="Home"
                component={Home}
                options={{ headerShown: false }}
            />
            <Tab.Screen
                name="Reminders"
                component={Reminders}
                options={{ headerShown: false }}
            />
            <Tab.Screen
                name="Settings"
                component={Settings}
                options={{ headerShown: false }}
            />
        </Tab.Navigator>
    );
};

const Navigator = () => {
    const Stack = createNativeStackNavigator();

    return (
        <NavigationContainer>
            <Stack.Navigator
                screenOptions={{ headerShown: false }}
                initialRouteName="Welcome"
            >
                <Stack.Screen name="Welcome" component={WelcomeScreen} />
                <Stack.Screen name="Features" component={Features} />
                <Stack.Screen name="SignIn" component={SignIn} />
                <Stack.Screen name="Register" component={Register} />
                <Stack.Screen name="BottomNavbar" component={BottomNavbar} />
            </Stack.Navigator>
        </NavigationContainer>
    );
};

export default Navigator;

主屏幕组件

import {
    View,
    Text,
    SafeAreaView,
    StyleSheet,
    TouchableOpacity,
    ScrollView,
} from "react-native";
import React from "react";
import { Header, Image, Icon } from "react-native-elements";
import { useFonts } from "expo-font";
import ServiceCard from "../components/ServiceCard";
import PetCard from "../components/PetCard";

const SignOut = ({ navigation }) => {
    return (
        <TouchableOpacity
            onPress={() => {
                navigation.navigate("SignIn");
            }}
        >
            <Icon name="logout" color="black" size={20} />
        </TouchableOpacity>
    );
};

const Home = () => {
    const [loaded, error] = useFonts({
        Montserrat: require("../assets/fonts/Montserrat-Regular.ttf"),
    });
    if (!loaded) {
        return null;
    }
    const url1 =
        "https://images.unsplash.com/photo-1530281700549-e82e7bf110d6?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=388&q=80";
    const url2 =
        "https://images.unsplash.com/photo-1560807707-8cc77767d783?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=435&q=80";
    const url3 =
        "https://images.unsplash.com/photo-1543466835-00a7907e9de1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=774&q=80";
    return (
        <View style={styles.screen}>
            <Header
                leftComponent={{
                    icon: "menu",
                    color: "black",
                }}
                rightComponent={<SignOut />}
                centerComponent={{
                    text: "PetPapa",
                    color: "black",
                    style: {
                        fontFamily: "Montserrat",
                        fontSize: 20,
                    },
                }}
                barStyle="dark-content"
                backgroundColor="white"
                containerStyle={styles.header}
            />
            <View style={styles.community}>
                <View style={styles.commOffer}>
                    <View>
                        <Text style={styles.commOfferTitle}>Join our</Text>
                        <Text style={styles.commOfferTitle}>
                            community today!
                        </Text>
                    </View>
                    <TouchableOpacity style={styles.btn}>
                        <Text style={styles.commOfferJoin}>Join Now</Text>
                    </TouchableOpacity>
                </View>
                <Image
                    source={{
                        uri: "https://imgur.com/nB4Xm1Z.png",
                    }}
                    style={styles.commDog}
                />
            </View>
            <View style={styles.listView}>
                <View style={styles.topText}>
                    <Text style={styles.title}>Services</Text>
                    <TouchableOpacity>
                        <Text style={styles.option}>See more</Text>
                    </TouchableOpacity>
                </View>
                <ServiceCard />
            </View>
            <View style={styles.listView}>
                <View style={styles.topText}>
                    <Text style={styles.title}>My Pets</Text>
                    <TouchableOpacity>
                        <Text style={styles.option}>See all</Text>
                    </TouchableOpacity>
                </View>
                <ScrollView
                    style={styles.petView}
                    horizontal={true}
                    showsHorizontalScrollIndicator={true}
                    persistentScrollbar={true}
                >
                    <PetCard name="Miles" Img={url1} />
                    <PetCard name="Jack" Img={url2} />
                    <PetCard name="Ellie" Img={url3} />
                </ScrollView>
            </View>
        </View>
    );
};

const styles = StyleSheet.create({
    screen: {
        height: "100%",
        backgroundColor: "white",
        alignItems: "center",
    },
    header: {
        backgroundColor: "white",
        height: 80,
    },
    community: {
        backgroundColor: "#1976D2",
        height: "15%",
        width: "80%",
        borderRadius: 20,
        marginTop: 50,
        flexDirection: "row",
        justifyContent: "space-around",
    },
    commDog: {
        marginTop: 10,
        marginRight: 15,
        height: 105,
        width: 75,
    },
    commOffer: {
        marginTop: 10,
        flexDirection: "column",
        justifyContent: "space-around",
    },
    commOfferTitle: {
        color: "white",
        fontFamily: "Montserrat",
        fontSize: 16,
    },
    btn: {
        backgroundColor: "#FFC107",
        width: "50%",
        borderRadius: 10,
    },
    commOfferJoin: {
        color: "white",
        margin: 5,
    },
    listView: {
        marginTop: 50,
        width: "80%",
    },
    topText: {
        flexDirection: "row",
        justifyContent: "space-between",
        alignItems: "center",
    },
    title: {
        fontFamily: "Montserrat",
        fontWeight: "600",
    },
    option: {
        fontFamily: "Montserrat",
        opacity: 0.4,
    },
    block: {
        backgroundColor: "#FF5677",
        width: 75,
        height: 100,
        justifyContent: "center",
        alignItems: "center",
        marginTop: 25,
        borderRadius: 20,
    },
    petView: {
        width: "100%",
        backgroundColor: "white",
        height: 250,
    },
});
export default Home;

我的目录结构:

项目的目录结构

首先,您需要将导航道具添加到主屏幕组件

const Home = ({navigation}) => {
    const [loaded, error] = useFonts({
        Montserrat: require("../assets/fonts/Montserrat-Regular.ttf"),
    });
   ...

然后您需要将导航道具传递给注销组件

 <Header
    leftComponent={{
       icon: "menu",
       color: "black",
    }}
    rightComponent={<SignOut navigation={navigation} />}
    ...

您还可以使用反应导航中的 useNavigation 挂钩

import { useNavigation } from '@react-navigation/native';

const SignOut = ({}) => {
    const navigation = useNavigation()
    return (
        <TouchableOpacity
            onPress={() => {
                navigation.navigate("SignIn");
            }}
        >
            <Icon name="logout" color="black" size={20} />
        </TouchableOpacity>
    );
};

如果您想创建登录流程,那么您应该使用身份验证流程,我认为这是最佳实践和推荐方式

当前流程中的问题如果您注销并导航到登录页面一次然后如果您从您的应用程序导航回来然后作为堆栈导航的行为它只会弹出当前屏幕并且它将再次导航到主屏幕这不是应该的正确的。

可以从 react-navigation 官方文档https://reactnavigation.org/docs/auth-flow/ 了解

如果你想要一个视频教程如何使用 redux(状态管理库)实现身份验证流程那么我有视频教程你可以学习这个视频 -> https://youtu.be/cm1oJ7JmW6c

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM