How to setup Top tabs with expo-router? #294
Replies: 16 comments 14 replies
-
@bhatvikrant Did you get a solution for this. |
Beta Was this translation helpful? Give feedback.
-
Yes, I made use of react-native-tab-view package.
On Tue, 28 Feb 2023 at 2:54 PM, Hudson Luseno ***@***.***> wrote:
@bhatvikrant <https://github.com/bhatvikrant> Did you get a solution for
this.
—
Reply to this email directly, view it on GitHub
<#294 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AMDCPMN5ULT6DKXZGP5WQYDWZW73NANCNFSM6AAAAAAVANQYYM>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Regards,
Vikrant Bhat
Software Engineer, Razorpay
|
Beta Was this translation helpful? Give feedback.
-
Did you manage to use the directory structure to define your routes? Or did you use the library ( Maybe it is possible to use the Or maybe I've missed something on the documentation about the |
Beta Was this translation helpful? Give feedback.
-
Here's what I'm doing, based on this example, but updated a little: import type {ParamListBase, TabNavigationState} from '@react-navigation/native';
import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs';
import type {
MaterialTopTabNavigationOptions,
MaterialTopTabNavigationEventMap,
} from '@react-navigation/material-top-tabs';
import {withLayoutContext} from 'expo-router';
const {Navigator} = createMaterialTopTabNavigator();
export const MaterialTopTabs = withLayoutContext<
MaterialTopTabNavigationOptions,
typeof Navigator,
TabNavigationState<ParamListBase>,
MaterialTopTabNavigationEventMap
>(Navigator); Have not tested yet, but I think that's approximately right. |
Beta Was this translation helpful? Give feedback.
-
Take a look to this project, it's from @EvanBacon himself https://github.com/EvanBacon/expo-router-top-tabs |
Beta Was this translation helpful? Give feedback.
-
Hi everyone. I've created a blog on how you can use Material Top Tabs in expo-router |
Beta Was this translation helpful? Give feedback.
-
I've been looking up a way to place the tabs in the main layout file and i found it, if anybody knows a better way, let me know. import { Stack } from "expo-router"
function RootLayout() {
return (
<Stack>
<Stack.Screen redirect name="index"/>
<Stack.Screen name="(tabs)"/>
</Stack>
)
}
export default RootLayout |
Beta Was this translation helpful? Give feedback.
-
Got an implementation that allows us to exclude a tab: import {
createMaterialTopTabNavigator,
MaterialTopTabBar,
MaterialTopTabNavigationEventMap,
MaterialTopTabNavigationOptions,
} from '@react-navigation/material-top-tabs'
import { ParamListBase, TabNavigationState } from '@react-navigation/routers'
import { withLayoutContext } from 'expo-router'
const { Navigator } = createMaterialTopTabNavigator()
export const MaterialTopTabs = withLayoutContext<
MaterialTopTabNavigationOptions & { excludeScreens?: string[] },
typeof Navigator,
TabNavigationState<ParamListBase>,
MaterialTopTabNavigationEventMap
>(Navigator, (options) => {
return options.filter((o) => !o.name || !o.options?.excludeScreens?.includes(o.name))
})
export type TopTabsProps = Omit<Parameters<typeof MaterialTopTabs>[0], 'screenOptions'> & {
screenOptions?: MaterialTopTabNavigationOptions & { excludeScreens?: string[] }
}
export function excludeScreensAndAdjustIndex(
allRouteNames: string[],
excludeScreens: string[],
requestedIndex: number,
) {
// routeNames = [screen1, screen2, screen3, screen4, screen5]
// index = 0, 1, 2, 3, 4
// given excludedScreens = [screen2, screen4]
// iteration 1: indexMap = { 0: 0 }
// iteration 2: indexMap = { 0: 0, 1: 0 }
// iteration 3: indexMap = { 0: 0, 1: 0, 2: 1 }
// iteration 4: indexMap = { 0: 0, 1: 0, 2: 1, 3: 1 }
// iteration 5: indexMap = { 0: 0, 1: 0, 2: 1, 3: 1, 4: 2 }
// though indexMap 1 and 3 should never be called upon as their corresponding tabs aren't accessible through the interface
const indexMap: Record<number, number> = {}
let prevIndex = 0
const routeNames = allRouteNames.filter((n, i) => {
indexMap[i] = prevIndex
const isExcluded = excludeScreens.includes(n)
if (isExcluded) {
} else {
prevIndex += 1
}
return !isExcluded
})
return {
routeNames,
index: indexMap[requestedIndex],
}
}
export function TopTabs({ ...props }: TopTabsProps) {
const excludeScreens = typeof props.screenOptions === 'object' ? props.screenOptions.excludeScreens : undefined
return (
<MaterialTopTabs
tabBar={({ state, descriptors, ...tabBarProps }) => {
if (!excludeScreens || excludeScreens.length === 0) {
return <MaterialTopTabBar state={state} descriptors={descriptors} {...tabBarProps} />
}
const { index, routeNames } = excludeScreensAndAdjustIndex(state.routeNames, excludeScreens, state.index)
const routes = state.routes.filter((r) => !excludeScreens.includes(r.name))
const stateWithoutExcludedScreens = {
...state,
index,
routeNames,
routes,
}
return <MaterialTopTabBar state={stateWithoutExcludedScreens} descriptors={descriptors} {...tabBarProps} />
}}
{...props}
/>
)
} usage: export default function MyLayout() {
return (<TopTabs screenOptions={{ excludeScreens: ['screen-I-want-to-exclude'] }} />)
} That's with expo-router 3.4 Edited: update state index. Though it's only a partial solution. Ideally the index would be recalculated based on the original index value of the tab minus each tab removed that was there prior (so something like previousIndex - tabsRemoved) Edit 2: actually calculate index as per:
|
Beta Was this translation helpful? Give feedback.
-
At first, following this article https://reactnativepro.dev/posts/expo-router-top-tabs from @iam-rohid works, but after struggling a lot of time tweaking it to support hidden tabs, all possible solution is just hacking to make it disappear on the UI, but behind the scene it still renders, you have to use |
Beta Was this translation helpful? Give feedback.
-
i has lots of issue with |
Beta Was this translation helpful? Give feedback.
-
I will share code later with you
…On Sat, 9 Nov 2024, 6:50 pm Peter Arkhipov, ***@***.***> wrote:
I have a weird situation. The tabs are visible but the labels on them are
not. Maybe you have an idea?
***@***.***/native": "^6.0.2",
***@***.***/material-top-tabs": "^6.6.14",
"react-native-tab-view": "^4.0.1",
"react-native-pager-view": "6.3.0"
—
Reply to this email directly, view it on GitHub
<#294 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/APNJUSALRITMPBABZQR65Q3Z7YHI3AVCNFSM6AAAAAAVANQYYOVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTCMJZGY4DSMI>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
I think it has lots of compatibility issues. i would suggest you to use
components for the top-tab-navigation as i have also used that
import { StyleSheet, Text, View, StatusBar } from "react-native";
import { NavigationContainer } from ***@***.***/native";
import { createMaterialTopTabNavigator } from
***@***.***/material-top-tabs";
import { Tabs } from "expo-router";
import AboutPage from "./About";
import ContactPage from "./Contact";
import LandingPage from ".";
import LoginPage from "./Login";
import PrivacyPage from "./Privacy";
import TermsPage from "./Terms";
const TopTabs = createMaterialTopTabNavigator();
const RootLayout = () => {
return (
<NavigationContainer>
<TopTabs.Navigator>
<TopTabs.Screen component={LandingPage} name="index" />
<TopTabs.Screen component={ContactPage} name="Contact" />
<TopTabs.Screen component={LoginPage} name="Login" />
<TopTabs.Screen component={PrivacyPage} name="Privacy" />
<TopTabs.Screen component={TermsPage} name="Terms" />
</TopTabs.Navigator>
</NavigationContainer>
);
};
export default RootLayout;
On Sat, Nov 9, 2024 at 6:58 PM Abdul Wajid Afridi ***@***.***>
wrote:
… I will share code later with you
On Sat, 9 Nov 2024, 6:50 pm Peter Arkhipov, ***@***.***>
wrote:
> I have a weird situation. The tabs are visible but the labels on them are
> not. Maybe you have an idea?
> ***@***.***/native": "^6.0.2",
> ***@***.***/material-top-tabs": "^6.6.14",
> "react-native-tab-view": "^4.0.1",
> "react-native-pager-view": "6.3.0"
>
> —
> Reply to this email directly, view it on GitHub
> <#294 (reply in thread)>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/APNJUSALRITMPBABZQR65Q3Z7YHI3AVCNFSM6AAAAAAVANQYYOVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTCMJZGY4DSMI>
> .
> You are receiving this because you commented.Message ID:
> ***@***.***>
>
|
Beta Was this translation helpful? Give feedback.
-
Just for the information: I downgraded to "react-native-tab-view": "^3.5.2" and everything seems to be working |
Beta Was this translation helpful? Give feedback.
-
So i think you can stick with old versions for now and then upgrade to
latest when its solved
…On Mon, 11 Nov 2024, 3:52 pm Peter Arkhipov, ***@***.***> wrote:
Just for the information:
"react-native-tab-view": "^4.0.1" is not compatible with
@react-navigation/native v6.x even then using without
@react-navigation/material-top-tabs
I downgraded to "react-native-tab-view": "^3.5.2" and everything seems to
be working
—
Reply to this email directly, view it on GitHub
<#294 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/APNJUSBBXXBGTAIAB7UDKZT2ACEAFAVCNFSM6AAAAAAVANQYYOVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTCMRRGMZTAMA>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
check your packages with expo doctor and install compatible versions
…On Thu, Nov 28, 2024 at 10:12 AM Marcos Lacoa ***@***.***> wrote:
"react-native-tab-view": "^3.5.2",
and what else are u using?
I have
***@***.***/material-top-tabs": "^6.6.13",
***@***.***/native": "^6.0.2",
And im dealing with
"Error: Couldn't register the navigator. Have you wrapped your app with
'NavigationContainer'?"
Two weeks ago i didnt see this error using SDK 51. Now that i upgraded, i
have it.
Here is the error:
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { createMaterialTopTabNavigator,
MaterialTopTabNavigationOptions,
MaterialTopTabNavigationEventMap } from
***@***.***/material-top-tabs';
import { withLayoutContext } from 'expo-router';
import { ParamListBase, TabNavigationState } from
***@***.***/native';
import { useFont } from '@/context/FontContext';
import LoadingComponent from '@/components/LoadingComponent';
const { Navigator } = createMaterialTopTabNavigator();
export const MaterialTopTabs = withLayoutContext<
MaterialTopTabNavigationOptions,
typeof Navigator,
TabNavigationState,
MaterialTopTabNavigationEventMap
(Navigator);
const Layout = () => {
const { fontsLoaded } = useFont();
if (!fontsLoaded) {
return ;
}
return (
<MaterialTopTabs
screenOptions={{
tabBarLabelStyle: { fontSize: 12, fontFamily: 'Bold' },
tabBarActiveTintColor: 'black',
tabBarIndicatorStyle: { backgroundColor: '#BAC500' },
}}
>
<MaterialTopTabs.Screen name="threads" options={{ tabBarLabel: 'Threads'
}} />
<MaterialTopTabs.Screen name="threads2" options={{ tabBarLabel: 'Threads
2' }} />
);
};
export default Layout;
—
Reply to this email directly, view it on GitHub
<#294 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/APNJUSAVF3TFKF5RGCEUQJT2C2Q3VAVCNFSM6AAAAAAVANQYYOVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTCNBQGIYTINY>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
Is it possible to do this without external lib? 🙈 |
Beta Was this translation helpful? Give feedback.
-
How to set up Top tabs with expo-router? A code snippet or docs will be helpful.
A way without using react-navigation directly would be great.
Beta Was this translation helpful? Give feedback.
All reactions