Learning React Native and I've run into a navigation issue using createBottomTabNavigator.
I have my screen displayed with 2 links on the bottom tab. Link 1 - Novels, Link 2 - Profile.
When I click on Link 2, I want to go to my profile screen (which it does) but I want to replace the bottom tab with a new one (which it doesn't).
I've tried using the tabPress event and I can see using console.log that it catches the event, but when I add the navigation param it stops working.
here's the relevant code:
const Stack = createStackNavigator();
const BottomTab = createBottomTabNavigator();
const headerTitle = "My Title";
function NovelsStack() {
return (
<Stack.Navigator screenOptions={{
headerStyle: {
backgroundColor: '#000',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 16,
},
}}>
<Stack.Screen name="Home" component={HomeScreen} options={{ headerTitle: () => <HeaderTitle title={headerTitle} /> }} />
<Stack.Screen name="Novels" component={TabNavigation} options={{ headerTitle: () => <HeaderTitle title={headerTitle} /> }} />
<Stack.Screen name="Novel" component={SelectedNovelNavigation} options={{ headerTitle: () => <HeaderTitle /> }} />
<Stack.Screen name="Profile" component={ProfileNavigation} options={{ headerTitle: () => <HeaderTitle title={headerTitle} /> }} />
</Stack.Navigator>
);
}
function TabNavigation() {
return (
<BottomTab.Navigator
tabBarOptions={{
labelStyle: styles.mainTabBarLabels
}}
>
<BottomTab.Screen name="Novels" options={{ title: "Novels" }} component={NovelsScreen} />
{isAuthenticatedUser() ? (<BottomTab.Screen name="Profile" component={ProfileScreen} />)
: (<BottomTab.Screen name="Login" component={LoginScreen} listeners={({ navigation, route }) => ({
tabPress: e => {
// Prevent default action
console.log(navigation)
e.preventDefault();
},
})} />)
}
</BottomTab.Navigator>
);
}
function ProfileNavigation() {
return (
<BottomTab.Navigator
tabBarOptions={{
labelStyle: styles.novelsTabBarLabels
}}>
<BottomTab.Screen name="Profile" component={ProfileScreen} options={{ title: "Profile" }} />
</BottomTab.Navigator>
);
}
function SelectedNovelNavigation() {
return (
<BottomTab.Navigator
tabBarOptions={{
labelStyle: styles.novelsTabBarLabels
}}>
<BottomTab.Screen name="Novel" component={NovelScreen} />
<BottomTab.Screen name="Comments" component={CommentsScreen} options={{ title: "Comments" }} />
<BottomTab.Screen name="Ratings" component={RatingsScreen} options={{ title: "Ratings" }} />
<BottomTab.Screen name="Related" component={RelatedNovelsScreen} options={{ title: "Related" }} />
</BottomTab.Navigator>
)
}
What I want to happen is when the user presses the "Profile" tab on the TabNavigation Stack, that the navigation takes the user to show the ProfileNavigation where I can add additional profile tabs, but I just can't get that hooked up correctly. Been looking at the docs and other posts about it, but still stuck.
Thanks in advance for any help
As usual, once you reach out for help you get the answer. In the docs here (https://reactnavigation.org/docs/bottom-tab-navigator/) and here (https://reactnavigation.org/docs/stack-actions/#replace) I can customize the tabBar and use the navigation.replace.
The good ole docs, I was all around it, just didn't see it.
Related
I have a screen with two routes pointing to it. These two routes are in a BottomTabNavigator. My problem is that the target screen is rendered twice. A different rendering for each route.
<Tab.Screen name="Home" component={ HomeScreen } options={{ title: 'Home' }} />
<Tab.Screen name="NewProduct" component={ HomeScreen } options={{ title: 'Neues', lazy:false }} />
Is there any way to do this without double rendering?
This was my solution:
<Tab.Screen name="Home" component={ HomeScreen } options={{ title: 'Home' }} />
<Tab.Screen
name="New"
component={HomeScreen}
options={({ navigation }) => ({
tabBarButton: (props) => (
<TouchableOpacity
style={{
}}
onPress={() => {
setNewProductInput(true);
navigation.navigate('Home');
}}
>
<Text>New</Text>
</TouchableOpacity>
),
})}
/>
import { createMaterialTopTabNavigator } from '#react-navigation/material-top-tabs';
const Tab = createMaterialTopTabNavigator();
function MyTabs() {
return (
<Tab.Navigator
initialRouteName="Feed"
screenOptions={{
tabBarActiveTintColor: '#e91e63',
tabBarLabelStyle: { fontSize: 12 },
tabBarStyle: { backgroundColor: 'powderblue' },
}}
>
<Tab.Screen
name="Feed"
component={Feed}
options={{ tabBarLabel: 'Home' }}
/>
<Tab.Screen
name="Notifications"
component={Notifications}
options={{ tabBarLabel: 'Updates' }}
/>
<Tab.Screen
name="Profile"
component={Profile}
options={{ tabBarLabel: 'Profile' }}
/>
</Tab.Navigator>
);
}
I am using the above code. I am trying to get active tab index and name. So i can do some condition base work. but not able to get tab index and name so any help here.
Hi~ Have you already solved it?
You just need to make a few modifications in your code.
your code
<Tab.Screen
name="Feed"
component={Feed}
options={{ tabBarLabel: 'Home' }}
/>
change to this code
<Tab.Screen
name="Feed"
options={{ tabBarLabel: 'Home' }}
>
{props => <Feed {...props} />}
</Tab.Screen>
In this way, you can check 'name' and 'key' as props in the component.
example:
route:
name: "Feed"
key: "Feed-your key code"
params: undefined
Symbol(CHILD_STATE): undefined
__proto__: Object
__proto__: Object
Hope this helps you!
Problem:
When I navigate to the Stack inside the Material Bottom the first time, all works fine, after that you change tab and when you return the content don't render any more.
Expected behavior:
Every time you select the tab the Stack must be render. In other words, I am able to see the content of the Stack inside the Tab every time I navigate to the Tab.
package
version
#react-navigation/native
6.0.6
#react-navigation/material-bottom-tabs
6.0.9
#react-navigation/native-stack
6.2.5
react-native-safe-area-context
3.3.2
react-native-screens
3.8.0
react-native
0.64.2
expo
43.0.0
Faced the same problem.
Found solution here: https://github.com/software-mansion/react-native-screens/issues/1197#issuecomment-993682256
You should wrap your nested navigator with a View that has collapsable false.
Example with my code:
const MealsNavigator = () => (
<NavigationContainer>
<TabNavigator />
</NavigationContainer>
)
const TabNavigator = () => (
<Tab.Navigator initialRouteName="Meals" {...TabProps} >
<Tab.Screen name="Meals" component={StackNavigator} options={{ headerShown: false, tabBarIcon: ({ color }) => (<Ionicons name='ios-restaurant' size={24} color={color} />), tabBarColor: Colors.primaryColor }} />
<Tab.Screen name="Favorites" component={FavoritesScreen} options={{ tabBarIcon: ({ color }) => (<Ionicons name='ios-star' size={24} color={color} />), tabBarLabel: 'Favorites!', tabBarColor: Colors.accentColor }} />
</Tab.Navigator>
)
const StackNavigator = () => (
<View style={{ flex: 1 }} collapsable={false}>
<Stack.Navigator initialRouteName="Categories" screenOptions={{
headerStyle: { backgroundColor: Platform.OS === "android" ? Colors.primaryColor : '' }, headerTintColor: Platform.OS === "android" ? 'white' : Colors.primaryColor
}} >
<Stack.Screen name="Categories" component={CategoriesScreen} options={{ title: 'Meal Categories' }} />
<Stack.Screen name="CategoryMeals" component={CategoryMealsScreen} options={({ route }) => ({ title: route.params.title })} />
<Stack.Screen name="MealDetail" component={MealDetailScreen} options={({ route }) => ({ title: route.params.title })} />
</Stack.Navigator>
</View>
)
I want to hide bottom tabbar on product details page. Bottom tabbar should appear only on home, profile and orders screen, not on product details page and also not on product image details screen.
Below is my code:
I used this animated tabbar
import { AnimatedTabBarNavigator } from "react-native-animated-nav-tab-bar";
here is the code:
const Tabs = AnimatedTabBarNavigator();
const AppNavigator = () => (
<Tabs.Navigator
tabBarOptions={{
activeTintColor: colors.white,
inactiveTintColor: colors.primary,
activeBackgroundColor : "#3f5393",
}}
initialRouteName={"Home"}
appearance={{
tabBarBackground : colors.primary,
topPadding : 10,
horizontalPadding : 10,
dotCornerRadius : 8,
dotSize : 'small'
}}
>
<Tabs.Screen
name="My Orders"
component={MyorderStack}
options={{
tabBarIcon: ({ focused, color, size }) => (
<Image
source={require('../assets/order.png')}
style={{
width : 20,
height : 20
}}
color={ colors.primary}
/>
)
}}
/>
<Tabs.Screen
name="Home"
component={HomeScreenStack}
options={{
tabBarIcon: ({ focused, color, size }) => (
<Image
source={require('../assets/home.png')}
style={{
width : 20,
height : 20
}}
/>
),
headerShown : true
}}
/>
<Tabs.Screen
name="Profile"
component={ProfileStack}
options={{
tabBarIcon: ({ focused, color, size }) => (
<Image
source={require('../assets/profile.png')}
style={{
width : 20,
height : 20
}}
color={focused ? color : colors.primary}
/>
)
}}
appearance ={{
topPadding : 0
}}
/>
</Tabs.Navigator>)
here is my home screen code: (MOBILE is main home screen, MOBILE1 and MOBILE2 are details page where i don't want bottom bar).
const HomeScreenStack = ({navigation,route}) => (
<Stack.Navigator>
<Stack.Screen name="MOBILE" component={ItemScreen} options={{headerTitleAlign: 'center'}} />
<Stack.Screen name="MOBILE1" component={Appdescription} options={{headerTitleAlign:'center'}} />
<Stack.Screen name="MOBILE2" component={ItemImageDetails} options={{headerTitleAlign:'center'}} />
</Stack.Navigator>
)
ItemScreen is the main home screen where the first code is appear homescreen.
Appdescription is the details screen of the product where i don't want to show bottom tab bar.
ItemImageDetails is the details screen from product detail where i also don't want to show bottom tab bar.
Here is the link which module i used for this bottom tab bar:
https://www.npmjs.com/package/react-native-animated-nav-tab-bar
Please try this in pageStack where you are navigating to product detail:
const ProductsStack = createStackNavigator({
ProductsScreen: ProductsScreen,
ProductDetail: {
screen: ProductDetailScreen,
navigationOptions: ({ navigation }) => ({
header: null,
tabBarVisible: true,
headerMode: "screen",
}),
},
NewProduct: NewProductScreen
});
Hope it will work. !!!
I solved it. Keep the
const Tabs = AnimatedTabBarNavigator();
function AppNavigator () {
return (
<Tabs.Navigator
initialRouteName={"Home"}>
<Tabs.Screen name="My Orders" component={MyorderStack} />
<Tabs.Screen name="Home" component={HomeScreenStack} />
<Tabs.Screen name="Profile" component={ProfileStack} />
</Tabs.Navigator>
);
}
const Stack = createStackNavigator();
export default function App({navigation}) {
return (
<Stack.Navigator>
<Stack.Screen name="Page1" component={AppNavigator}
options={{ headerShown: false }} /> //Keep first function name "AppNavigator here and Keep HeaderShown false"
<Stack.Screen name="Page2" component={Page2} /> //other all pages will not show the header
<Stack.Screen name="Page3" component={Page3} /> //other all pages will not show the header
<Stack.Screen name="Page4" component={Page4} /> //other all pages will not show the header
</Stack.Navigator>
);
}
How can I show BottomTabNavigation even on stacked screen? I have tried this for a few hours but really don't get it to work as expected.
So the thing I want to happen is, if I navigate to say for example the Title Screen, I still want to show the BottomTabNavigation. Any suggestions?
I can of course create a new navigation, but then it is sliding in from the side.
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
const HomeTabNavigator = () => {
return (
<Tab.Navigator
tabBarOptions={{
labelStyle: {textTransform: 'uppercase'},
style: {
backgroundColor: '#111111', //Färger på footerbar
borderTopColor: 'transparent',
borderBottomColor: 'transparent',
},
}}>
<Tab.Screen
name={'Concerts'}
component={ConcertsScreen}
options={{
tabBarIcon: ({tintColor}) => (
<Image
source={require('../../assets/icons/concerts.png')}
size={25}
/>
),
}}
/>
<Tab.Screen
name={'Docs'}
component={DocumentiesScreen}
options={{
tabBarIcon: ({tintColor}) => (
<Image source={require('../../assets/icons/docs.png')} size={25} />
),
}}
/>
<Tab.Screen
name={'Profile'}
component={ProfileScreen}
options={{
tabBarIcon: ({tintColor}) => (
<Image source={require('../../assets/icons/user.png')} size={25} />
),
}}
/>
</Tab.Navigator>
);
};
const Router = () => {
const {token, setToken} = useContext(TokenContext);
const {userFav, addFav, getFav} = useContext(UserContext);
const [isLoading, setLoading] = useState(true);
useEffect(() => {
setLoading(false);
setTimeout(() => {}, 1000);
}, []);
return (
<NavigationContainer>
{token ? (
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerTransparent: true,
noBorder: true,
}}
headerMode="float">
<Stack.Screen name={' '} component={HomeTabNavigator} />
<Stack.Screen name={'Concerts'} component={ConcertsScreen} />
<Stack.Screen name={'User Profile'} component={ProfileScreen} />
<Stack.Screen
name={'FavouritesScreen'}
component={FavouritesScreen}
/>
<Stack.Screen name={'Docs'} component={DocumentiesScreen} />
<Stack.Screen name={'AccountScreen'} component={AccountScreen} />
<Stack.Screen name={'Home of'} component={SearchScreen} />
<Stack.Screen name={'Artist'} component={ArtistScreen} />
<Stack.Screen name={'Title'} component={Videos} />
<Stack.Screen name={'PlayVideo'} component={PlayVideo} />
</Stack.Navigator>
) : (
<LoginScreen />
)}
</NavigationContainer>
);
};
You need to nest all your stack screens inside a tab screen.
The BottomTabNavigator disappear because you leave your Tab.Navigator component.
I hope this helps. If you want to navigate between screens that are related to a specific tab button, and have that tab button remain active while moving between these screens, you should set up a StackNavigation within that tab's component. By doing so, the tab button will remain active while navigating within its related screens.
On the other hand, if you want the TabNavigation to be visible throughout the whole application but some screens should not be displayed as tabs, you can add all screens inside the TabNavigation and specify in the options for those screens not to be displayed as tab buttons. That way, while in the screen without a tab button, the tabs will still be visible but none will be active. For example, you can do this for a screen called 'Title':
<Tab.Screen
name={'Title'}
component={Videos}
options={{
tabBarIcon: ({tintColor}) => (
<Image source={require('../../assets/icons/user.png')} size={25} />
),
tabBarButton: () => null <---- *this causes it to have no button*
}}
/>
I hope this helps!