使用 expo-router 链接到当前选项卡堆栈外部的路线,同时保持选项卡栏可见

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

我有一个使用选项卡模板 (

npx create-expo-app --template tabs
) 的博览会项目,目标是本机和网络。

对于这个例子,假设我有三页:

  • 探索(所有项目的列表)
  • 收藏夹(所有收藏的项目列表)
  • 详细信息(单个项目的详细信息,可以选择收藏它)

文件夹如下所示:

(tabs)
│   _layout.tsx
│   explore.tsx
│   favorites.tsx
│
details
│   _layout.tsx
│   [id].tsx
│
_layout.tsx

当我在探索或收藏夹页面中单击某个项目时,我希望能够从这两个页面链接到详细信息页面。但是,这会导致页面在选项卡导航顶部打开。我想在选项卡堆栈的上下文中打开它,保持选项卡导航可见。

现在我知道如果我像这样构造我的代码它会起作用:

(tabs)
│   _layout.tsx
│
└── explore
│   │   _layout.tsx
│   │   index.tsx
│   │   [id].tsx <- Details page
│
└── favorites
│   │   _layout.tsx
│   │   index.tsx
│   │   [id].tsx <- Details page
│
_layout.tsx

但这会导致网络出现重复的路由:

/explore/test-item
/favorites/test-item
。这也使得与它们进行深度链接变得困难。我研究了共享路线,但我无法理解它们在这种情况下如何工作(在我的项目中,路线的嵌套方式不同,所以它更像是
/profile/favorites/
/explore/
)两者都需要在各自的堆栈中打开
/details/test-item/
我正在使用
<Stack>
提供的
expo-router
组件,它没有
component
中的
react-navigation
属性。

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

我找到了一个有效的解决方案(有一个小警告 - 见下文)。

解决方案

使用 共享路由 将所有顶级选项卡路由和嵌套共享路由分组在一起,然后使用

_layout.tsx
segment
属性指定当前活动选项卡的顶级路由。

实施

考虑一个具有三个选项卡(主页、搜索和库)的应用程序,以及一个需要在每个选项卡堆栈中显示的嵌套项目屏幕。

首先设置以下文件结构:

app/
├── _layout.tsx // defines root stack with single (tabs) screen
└── (tabs)/
    ├── _layout.tsx
    └── (home,search,library)/
        ├── _layout.tsx
        ├── index.tsx
        ├── search.tsx
        ├── library.tsx
        └── item.tsx // This is a nested shared route and not a tab

在您的(选项卡)

_layout.tsx
文件中,确保每个选项卡指向相关组:

<Tabs screenOptions={{ headerShown: false }} >
  <Tabs.Screen name="(home)" options={{ title: 'Home' }} />
  <Tabs.Screen name="(search)" options={{ title: 'Search' }} />
  <Tabs.Screen name="(library)" options={{ title: 'Your Library' }} />
</Tabs>

然后,在您的(家庭、搜索、图书馆)共享路径

_layout.tsx
文件中,使用
segment
属性打开每个段并为每个选项卡定义每个根堆栈屏幕:

const Layout = ({ segment }) => {
    const rootScreen = useMemo(() => {
        switch (segment) {
            case '(home)':
                return <Stack.Screen name="index" options={{ title: 'Home' }} />
            case '(search)':
                return <Stack.Screen name="search" options={{ title: 'Search' }} />
            case '(library)':
                return <Stack.Screen name="library" options={{ title: 'Your Library' }} />
        }
    }, [segment])

    return (
        <Stack>
            {rootScreen}
            <Stack.Screen name="item" options={{ title: 'Item' }} />
        </Stack>
    )
}

export default Layout

说明

“共享路线”功能本质上是定义三个组中每一个组的“速记”。上面定义的文件结构使用这个“简写”,并且等同于: app/ ├── _layout.tsx // defines root stack with single (tabs) screen └── (tabs)/ ├── _layout.tsx ├── (home)/ │ ├── _layout.tsx │ ├── index.tsx │ └── item.tsx ├── (search)/ │ ├── _layout.tsx │ ├── search.tsx │ └── item.tsx └── (library)/ ├── _layout.tsx ├── library.tsx └── item.tsx

影响

导航到
    /item
  • 会将项目屏幕
    推到当前堆栈上
    导航到
  • (search)/item
  • 将推动搜索堆栈上的项目屏幕并切换到“搜索”选项卡 ✅
    
    
  • 注意事项

由于所有选项卡都是在(主目录、搜索、库)目录中定义的,因此可以从

all

选项卡访问此目录中的所有嵌套屏幕。这在实践中可能不是问题,但值得注意。

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