Multiple paths for same screen with a single rendering in react native - react-native

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>
),
})}
/>

Related

Get active Tab Name in material top tabs

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!

Stack nested inside Material Bottom Tab dont show the content when you navigate the second time (React Navigation v6)

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>
)

Always show BottomTabNavigation

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!

React has detected a change in the order of Hooks called by StackNavigator

I'm using StackNavigator, inside TabNavigator, inside Drawer Navigator.
Trying to redirect to nested Stacks but returns error.
Warning: React has detected a change in the order of Hooks called by StackNavigator. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks:
TypeError: undefined is not an object (evaluating 'prevDeps.length')
What's wront with that?
Why it doesnt redirect to stack.screen below main screen?
my redirect:
<TouchableOpacity style={styles.accessButton} onPress={() => navigation.navigate('Home', {
screen: 'Events'
})}>
My main.js (navigator)
return (
<NavigationContainer theme={NavigationTheme} ref={navigationRef}>
<StatusBar barStyle={darkMode ? 'light-content' : 'dark-content'} />
<Drawer.Navigator
drawerStyle={{ width: '100%' }}
drawerContent={(props) => <DrawerContent {...props} />}
>
<Drawer.Screen name="Startup" component={IndexStartupContainer} />
{isApplicationLoaded && BeforeLogin != null && (
<Drawer.Screen name="Main" component={BeforeLogin} />
)}
</Drawer.Navigator>
</NavigationContainer>
)
my tabbar navigator:
return (
<Tab.Navigator tabBarOptions={{showLabel: false}} lazy>
<Tab.Screen name="Home" component={HomeNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<AntDesign name="home" size={39} color={colors.text} />
);
},
}}
/>
<Tab.Screen name="SearchNavigator" component={SearchNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<AntDesign name="search1" size={39} color={colors.text} />
);
},
}}
/>
<Tab.Screen name="FAQNavigator" component={FAQNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<AntDesign name="questioncircleo" size={39} color={colors.text} />
);
},
}}
/>
<Tab.Screen name="ContactNavigator" component={ContactNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<Feather name="phone" size={39} color={colors.text} />
);
},
}}
/>
</Tab.Navigator>
)
and my HomeNavigator:
const HomeNavigator = ({ navigation }) => {
const Stack = createStackNavigator()
const { t } = useTranslation()
return (
<Stack.Navigator>
<Stack.Screen
options={headerStyle_1}
name='Index'
title={t('title.homepage')}
component={HomepageController}
/>
<Stack.Screen
options={headerStyle_1}
name='Events'
title={t('title.events')}
component={EventsController}
/>
</Stack.Navigator>
)
}

React Native Navigation v5 bottom navigation navigate to new stack

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.