尽管使用 expo-router 进行了正确的屏幕堆叠,但后退按钮始终显示“主页”

问题描述 投票:0回答:1

作为 ReactJS 的初学者,试图构建一个 React-Native 应用程序,我发现博览会是一个不错的选择。但由于某种原因,我无法从

documentation
中找到使用 expo-router 的好方法。

我不太确定需要多少信息才能获得任何帮助,但我将首先写下我的文件夹结构,然后是屏幕的外观。最后我也会写下部分代码。如果此问题还需要任何其他信息,请告诉我。

我的文件夹结构如下所示:

app/
├── settings/
│   ├── _layout.tsx
│   ├── index.tsx
│   └── auth/
│       ├── _layout.tsx
│       ├── index.tsx
│       ├── login.tsx
│       └── signup.tsx
├── _layout.tsx
├── [missing].tsx
├── chat.tsx
└── index.tsx

由于

expo-router
是一个基于文件的路由系统,我希望屏幕像
Home -> Settings -> Auth
一样堆叠,但是当我从
Home
屏幕转到
Settings
页面,然后从那里移动到
Auth
时页面,不知何故后退按钮仍然带我回到
Home
屏幕而不是
Settings
页面。

仅供参考,这是我的

Home
页面: Home Page

从那里,我单击右上角的按钮(

Settings
页面的标题栏)移动到
Home
页面,如下所示: Settings Page

如果我点击

Login / Signup
按钮,我们会转到第三页
Auth
,但后退按钮仍然显示
Home Page
。它看起来像这样: Login Page

我的

app/_layout.tsx
看起来像:

import { Stack, router } from "expo-router";
import { ThemeProvider, DefaultTheme, DarkTheme } from "@react-navigation/native";
import { StatusBar, useColorScheme } from "react-native";
import { SettingsButton } from "../src/components";

export default function HomePageLayout() {
  const colorScheme = useColorScheme();
  return (
    <ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
      <StatusBar barStyle="default" />
      <Stack
        screenOptions={{ headerShown: false, headerTintColor: "white", headerStyle: { backgroundColor: "black" }, headerTitleStyle: { fontWeight: "bold" } }}
      >
        <Stack.Screen
          name="index"
          options={{
            title: "Home Page", headerShown: true, headerRight: () => (
              <SettingsButton
                color="white"
                onPressFunction={() => router.push("settings")}
              />
            ),
          }}
        />
        <Stack.Screen
          name="settings"
          options={{ title: "Settings", headerShown: true }}
        />
        <Stack.Screen
          name="[missing]"
          options={{ title: "Page Not Found", headerShown: true }}
        />
      </Stack>
    </ThemeProvider>
  );
}

我的

app/index.tsx
看起来像这样:

import { Stack, router } from "expo-router";
import { View } from "react-native";
import { CustomButton, bodyStyles } from "../src/components/";

export default function App() {
  return (
    <>
      <View style={[bodyStyles.container, { width: "100%" }]}>
        <View style={bodyStyles.buttonContainer}>
          <CustomButton
            buttonTitle="Chat"
            onPressFunction={() => console.log("Chat pressed")}
          />
        </View>
      </View>
    </>
  );
}

settings/_layout.tsx

import { Stack } from "expo-router";

export default function SettingsLayout() {
  return (
    <Stack>
      <Stack.Screen name="index" options={{ headerShown: false }} />
      <Stack.Screen name="auth" options={{ headerShown: false }} />
    </Stack>
  );
}

settings/index.tsx

import React from "react";
import { View } from "react-native";
import { router } from "expo-router";
import { bodyStyles, CustomButton } from "../../src/components";

export default function SettingsScreen() {
  return (
    <View style={[bodyStyles.container, bodyStyles.buttonContainer]}>
      <CustomButton
        buttonTitle="Login / Signup"
        onPressFunction={() => router.push("/settings/auth")}
      />
    </View>
  );
}

settings/auth/_layout.tsx

import { Stack } from "expo-router";

export default function AuthLayout() {
  return (
    <Stack>
      <Stack.Screen name="index" options={{ headerShown: false }} />
      <Stack.Screen name="login" options={{ headerShown: false, presentation: "modal" }} />
      <Stack.Screen name="signup" options={{ headerShown: false, presentation: "modal" }} />
    </Stack>
  );
}

settings/auth/index.tsx

import React from "react";
import { View, Text } from "react-native";
import { CustomButton, bodyStyles } from "../../../src/components";
import { router } from "expo-router";

export default function AuthScreen() {
  return (
    <View style={bodyStyles.container}>
      <Text style={bodyStyles.header1}>Welcome user!!</Text>
      <Text style={bodyStyles.header2}>Please login or create account!</Text>
      <View style={bodyStyles.buttonContainer}>
        <LoginButton />
        <SignupButton />
        <CustomButton
          buttonTitle="Go Back"
          onPressFunction={() => router.back()}
        />
      </View>
    </View>
  );
}

在最后一页上,当我按下

router.back()
按钮时调用
Go Back
时,我会转到
Settings
页面。这应该意味着堆栈上的最后一个屏幕是
Settings
页面,而不是
Home Page
,但后退按钮仍然设置为
Home Page
页面中的
Auth

我已经提供了我认为必要的尽可能多的背景信息。请让我知道我做错了什么。另外,如果我没有遵循 React-Native 应该遵循的任何最佳实践,请随时告诉我。

提前谢谢您!

编辑:我意识到,如果我将屏幕的

headerShown: true
选项放在
settings/_layout
auth/_layout
下,我会得到另一个级别的标题,该标题将返回到
Settings
页面。这意味着,每次我在
<Stack>
中调用另一层
_layout.tsx
时,它只会在我的屏幕所在位置创建一个单独的堆栈。屏幕中最顶部的标题始终指向
Home Page
,因为这是最顶部堆栈上唯一的其他选项。

所以我的问题本质上是,定义充当单个堆栈的嵌套堆栈的理想方法是什么,即使路由是嵌套的?

react-native expo react-navigation expo-router
1个回答
0
投票

我找到了一种方法,可以在未出现后退按钮的页面的标题上手动放置后退按钮。

例如,我将

app/settings/_layout.tsx
文件更改为:

import { Stack, router } from "expo-router";
import { Ionicons } from "@expo/vector-icons";
import { Platform } from "react-native";

export default function SettingsLayout() {
  const backIcon = Platform.OS === "ios" ? "chevron-back" : "arrow-back-sharp";

  return (
    <Stack
      screenOptions={{
        headerShown: true,
        headerTintColor: "white",
        headerStyle: { backgroundColor: "black" },
        headerTitleStyle: { fontWeight: "bold" },
        headerBackTitleVisible: false,
      }}
    >
      <Stack.Screen
        name="index"
        options={{
          title: "Settings",
          headerLeft: () => (
            <Ionicons
              name={backIcon}
              size={25}
              color="white"
              onPress={() => router.back()}
            />
          ),
        }}
      />
      <Stack.Screen name="auth" options={{ title: "Authorize" }} />
    </Stack>
  );
}

这为我提供了一个适合所有看起来接近本机解决方案的平台的不错的解决方案。

但作为一个非本地解决方案,它也引入了一些问题。例如,在 Android 中,无论应用非本机解决方案 (

headerLeft
),标题都会显示在非常靠近
headerLeft
按钮的位置。

此解决方案虽然暂时修补了问题,但仍然没有完全解决创建单个屏幕堆栈同时具有多个

_layout.tsx
文件的多个嵌套路由的问题。

我现在发布解决方案,但如果有人有更好的解决方案以本机方式实现相同的后退按钮,请回答这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.