Dynamically update screen header title on React Native Tab Navigator - javascript

I am using React Native Tab navigator and I am trying to have my Screen route names as header but with no luck. The fact that the screens are rendered inside the Tab Navigator makes it so their headers are ignored. I have tried setting headerShown=true and many other things with no luck.
This is part of my App.js code:
const AppStack = createStackNavigator({
Navigation: {
screen: NavigationScreen,
navigationOptions: {
}
},
Route: {
screen: RouteScreen,
navigationOptions: {
// headerShown: false
headerTitle: 'TestTitle'
}
},
Confirm: {
screen: ConfirmScreen,
navigationOptions: {
// headerShown: false
headerTitle: 'TestTitle'
}
},
Find: {
screen: FindScreen,
navigationOptions: {
// headerShown: false
headerTitle: 'TestTitle'
}
},
Offer: {
screen: OfferScreen,
navigationOptions: {
// headerShown: false
headerTitle: 'TestTitle'
}
},
and here is my Navigation Screen code:
export default function NavigationScreen( {navigation}) {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ color, size }) => {
const icons = {
Home: 'home',
Profile: 'account',
Offer: 'car-hatchback',
Find: 'magnify'
};
return (
<MaterialCommunityIcons
name={icons[route.name]}
color='#E9446A'
size={30}
/>
);
},
})}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={HomeTabScreen} />
<Tab.Screen name="My Rides" children={()=><MyRidesScreen navigation={navigation}/>} />
<Tab.Screen name="Offer" children={()=><OfferScreen navigation={navigation}/>} />
<Tab.Screen name="Find" children={()=><FindScreen navigation={navigation}/>} />
</Tab.Navigator>
</NavigationContainer>
);
}
Any change attempted to the Tab.Screen routes via options is rendered on the bottom tab Names and not the screen header, as the parent screen is always Navigation Screen

Related

React Native: bottom tab press not working

in my react-native app I have a bottom tabs navigation, I added a tabPress listener to one of the screens but for some reason now all screens don't work, I can't navigate to a different screen when I tap the icons...
The objective was to lock a screen depending of the day but now ALL screens are locked for some reason and I can't navigate to ANY screen!
<Tab.Navigator /* options here... */>
<Tab.Screen name="Descubre" component={STACK1} />
<Tab.Screen name="Favoritos" component={STACK2}
listeners={{
tabPress: (e) => {
if(root.mapStore.isoWeekDay == 6)
{
e.preventDefault();
}
},
}}
/>
<Tab.Screen name="Pedidos" component={STACK3} />
<Tab.Screen name="Más" component={STACK4}/>
</Tab.Navigator>
I'm guessing this is the default behaviour stablished by React Native for this event, check section Listening to events​
If you want only to block one of the screens in this point, you could do the following:
<Tab.Navigator>
<Tab.Screen name="Screen 1" />
<Tab.Screen name="Screen 2"
options={{
tabBarButton: disabled ? DisabledTabBarButton : EnabledTabBarButton,
}}
/>
</Tab.Navigator>
Where DisabledTabBarButton is:
const DisabledTabBarButton = ({ style, ...props }: BottomTabBarButtonProps) => (
<Pressable disabled style={[{ opacity: 0.2 }, style]} {...props} />
)
And enabled one:
const EnabledTabBarButton = ({ style, ...props }: BottomTabBarButtonProps) => (
<Pressable style={[{ opacity: 1 }, style]} {...props} />
)
Also, you could do the following while creating your tab navigator:
const TabNavigator = createBottomTabNavigator({
First:{
screen: First,
},
Second:{
screen: Second,
},
Third:{
screen: Third,
}
}, defaultNavigationOptions: ({ navigation }) => ({
tabBarOnPress: ({ navigation, defaultHandler }) => {
if (
navigation.state.routeName === "Route disabled"
) {
return null;
}
defaultHandler();
},})

React Native tab navigator nested in stack navigator

I'm relatively new to React Native and am struggling with screens. I've gone through the nested navigation documentation (https://reactnavigation.org/docs/nesting-navigators/) which helped me setup the initial nav setup i have, but im having some issues.
I'm attempting to setup the app so it has the initial screen as a "Select User" which has no tab navigation. After selecting the user, you are redirected to a another screen which has tab navigation. I currently have it working however I am unable to access any route/props/params after the initial screen.
I've had to manually import navigation with import { useNavigation } from "#react-navigation/native"; and even though I'm providing params in the Navigation.push, trying to access {route} in my screens states that route is undefined.
My setup of the screens looks similar to below:
const Tab = createBottomTabNavigator();
const WelcomeStack = createStackNavigator();
const HomeStack = createStackNavigator();
const SettingsStack = createStackNavigator();
const Stack = createStackNavigator();
const WelcomeStackScreen = () => (
<WelcomeStack.Navigator>
<WelcomeStack.Screen
name="Welcome"
component={WelcomeScreen}
options={{ headerShown: false }}
/>
<WelcomeStack.Screen
name="SignUp"
component={SignUpScreen}
options={{ headerShown: false }}
/>
</WelcomeStack.Navigator>
);
const HomeStackScreen = () => {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen
name="Search"
component={SearchResultScreen}
options={({ navigation }) => ({
headerLeft: () => (
<Ionicons
name={"arrow-back"}
size={30}
color={colours.text}
style={{ paddingLeft: 15 }}
onPress={() => {
navigation.goBack();
}}
/>
),
})}
/>
<HomeStack.Screen
name="Select"
component={SelectScreen}
options={({ navigation, route }) => ({
title: route.params.name,
headerLeft: () => (
<Ionicons
name={"arrow-back"}
size={30}
color={colours.text}
style={{ paddingLeft: 15 }}
onPress={() => {
navigation.goBack();
}}
/>
),
})}
/>
<HomeStack.Screen name="Read" component={ReaderScreen} />
</HomeStack.Navigator>
);
};
function SettingsScreen() {
return (
<View
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
>
<Text>TBD</Text>
</View>
);
}
const SettingsStackScreen = () => (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
</SettingsStack.Navigator>
);
const TabNavigator = ({ route }) => (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
switch (route.name) {
case "Home":
iconName = focused ? "home" : "home-outline";
break;
case "Settings":
iconName = focused ? "list" : "list-outline";
break;
default:
break;
}
return <Ionicons name={iconName} size={size} color={color} />;
},
})}
tabBarOptions={{
activeTintColor: "tomato",
inactiveTintColor: "gray",
}}
>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsScreen}/>
</Tab.Navigator>
);
export default function App() {
return (
<NavigationContainer theme={navThemeOverride}>
<Stack.Navigator>
<Stack.Screen name="Welcome" component={WelcomeStackScreen} />
<Stack.Screen
name="TabNavigator"
component={TabNavigator}
options={{ headerShown: false }}
navigationOptions={{ gesturesEnabled: false }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
Below is a snippet from the Welcome screen navigation
navigation.push("TabNavigator", {
screen: "Home",
params: {
userId: userId,
},
});
Your Home screen you're trying to navigate to from your parent-tab-navigator ... is also a StackNavigator ... and you wanna navigate to Select screen I guess ... so there's an extra level needed for your navigation to work...
navigation.navigate('TabNavigator', {
screen: 'Home', // <--- StackNavigator
params: {
screen: 'Select', // <-- nested inside HomeStack
params: {
title: 'Your custom title for Select screen here ...',
},
},
});
Plus +
There's a double definition for route in your Tab navigator
const TabNavigator = ({ route }) => ( //<--- here
<Tab.Navigator
screenOptions={({ route }) => ({ // <- and here
Instead
function TabNavigator() {
return <Tab.Navigator screenOptions={({ route }) => ({})>{/* ...Tabs... */}</Tab.Navigator>;
}

How to override header title in react navigation 5

In my react native app i have stack navigator and tab navigator like:
const diagnoseNavigation = ({ navigation, language }) => {
return (
<Stack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: "#0089d8",
shadowOpacity: 0
},
headerTitleStyle: {
fontWeight: "bold",
color: "white",
textAlign: "center"
},
headerLeft: () => (
.......
)
}}
>
<Stack.Screen
name="Diagnose"
component={tabNav}
options={({ route, navigation }) => {
const routeName = getFocusedRouteNameFromRoute(route) ?? "Home";
switch (routeName) {
case "Screen1": {
return {
headerTitle:"Screen1",
headerRight: () => (
.......
)
};
}
case "Screen2": {
return {
headerTitle: "Screen2" //want to override this one
};
}
default: {
return {
headerTitle: "Home"
};
}
}
}}
/>
</Stack.Navigator>
);
};
Tab navigation:
const Tab = createBottomTabNavigator();
const tabNav = () => {
return (
<Tab.Navigator tabBarOptions={{ showIcon: true }}>
<Tab.Screen
name="Screen1"
component={Screen1Screen}
/>
<Tab.Screen
name="Screen2"
component={Screen2Screen}
/>
<Tab.Screen
name="Screen3"
component={recommendedNavigation}
/>
</Tab.Navigator>
);
};
Screen2
const Screen2Screen = ({ route, language }) => {
return (
<Stack.Navigator>
<Stack.Screen options={{ headerShown: false }} name="A" component={AScreen} />
<Stack.Screen
name="B"
component={BScreen}
options={() => {
return {
headerTitle: "ABC" //with this one
};
}}
/>
</Stack.Navigator>
);
};
In short i have stack navigatior, in that i have tab navigator. there are 3 tabs,what i want is in my tab 2(Screen2) there is a button when i click that button it should navigate to another page within the same tab.Then the title should be the "ABC" but it still shows "Screen2" under that ABC. ie, not overriding the header title?
Something like this:
You have to pass showLabel props to hide the header in your tababrOptions.
<Tab.Navigator tabBarOptions={{ showIcon: true , showLabel: false,
}}>

React Navigation - Go back to a screen in another Navigator

I have a createBottomTabNavigator() in a screen of my createStackNavigator.
Basically i have my App.js like this :
const RootStack = createStackNavigator(
{
Login: Login,
Register: Register,
Principal: {
screen: Principal,
navigationOptions: {
headerShown: false,
},
},
},
{
initialRouteName: "Login"
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
And in my "Principal.js" i'm creating a createBottomTabNavigator()
const Tab = createBottomTabNavigator();
class ConnectNavigator extends React.Component {
(....)
render() {
return (
<NavigationContainer>
<Tab.Navigator (....)>
<Tab.Screen name="Home" component={CheckPage} />
<Tab.Screen name="Settings" component={SettingPage} />
</Tab.Navigator>
</NavigationContainer>
);
}
}
Basically, in my SettingPage, i want to go back in my "Login" screen. But because i have two Navigator, i can't. I know, i'm not very clear, but my question is : "Can i go in my Login Screen when i'm in a Tab.Screen ?"
I have already tried to do this.props.navigation.navigate('Login') in my Settings screen but i have this error
The action 'NAVIGATE' with payload {"name":"Login","params":{"screen":"Login"}} was not handled by any navigator.
Do you have a screen named 'Login'?
If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.
I'm not sure if you tried what's written in the documentation mentioned in the error, but you could try something like this:
navigation.navigate('Home', { screen: 'Login' });
Edit:
You could re-structure it a bit:
const AppNavigation = () => <NavigationContainer>
<Stack.Navigator initialRouteName={"Login"}>
<Stack.Screen
name={"Login"}
options={{
headerStyle: styles.loginHeader,
headerShown: false,
}}
component={LaunchScreen}
/>
<Stack.Screen
options={{ headerShown: false }}
name={"Principal"}
component={BottomTabNavigation}
/>
</NavigationContainer>
const Tab = createBottomTabNavigator()
const BottomTabNavigation = () => {
return (
<Tab.Navigator
initialRouteName={"Home"}
>
<Tab.Screen name="Home" component={CheckPage} />
<Tab.Screen name="Settings" component={SettingPage} />
</Tab.Navigator>
)
}

How do I hide one icon in ReactNative React Navigation Bottom Tab

Im making an app in React Native, and am looking to have a page that displays the bottom navigation bar but isn't directly on that navigation bar, i.e. it is sort of a child of another page though does not need to be access through the bottom Nav.
However, whenever I take it out of the bottom tab navigator it won't hide the icon, and if it is not added it wont allow me to see the bottom nav when I go to that page.
The code is as follows;
{
History: {
screen: HistoryScreen,
navigationOptions: {
tabBarIcon: ({ focused, tintColor }) =>
<Icon
focused={focused}
color={{ tintColor }}
name="history"
size={20}
zIdex="13"
solid
/>
}
},
Home: {
screen: HomeScreen,
navigationOptions: {
tabBarIcon: ({ focused, tintColor }) =>
<Icon
focused={focused}
color={ Colors.gyroscopicOrgane }
name="home"
size={20}
zIdex="13"
solid
/>
}
},
ConcreteTest: {
screen: ConcreteTestScreen,
navigationOptions: {
tabBarIcon: ({ focused,tintColor }) => <
Icon name="cog"
focused={focused}
color={{ tintColor }}
size={20}
zIdex="13"
solid
/>
}
},
Settings: {
screen: SettingsScreen,
navigationOptions: {
tabBarIcon: ({ }) => {
showIcon: false
}
}
}
},
{
tabBarOptions: {
activeTintColor: "#E66F25",
inactiveTintColor: "#B8BBC4",
showLabel: false
}
}
)
const AppStack = createStackNavigator({
Home: HomeScreen,
History: HistoryScreen,
ConcreteTest: ConcreteTestScreen,
Settings: SettingsScreen,
});
const AuthStack = createStackNavigator({
Launch: LaunchScreen,
Login: LoginScreen,
SignUp: SignUpScreen
});
export default createAppContainer(
createSwitchNavigator(
{
Loading: LoadingScreen,
Launch: LaunchScreen,
Settings: SettingsScreen,
App: AppTabNavigator,
Features: AppStack,
Auth: AuthStack
},
{
initialRouteName: "Loading"
}
)
)
It might be helpful to attach a screenshot of your layout. Try positioning your element absolutely (position: absolute) and then using top: left: bottom: right: to align it. If you need it to display conditionally, try setting a variable elementVar = null; and then if (needs to be displayed) {elementVar = YOUR_ELEMENT_CONTENT} then simply use {elementVar} in your render(return()) function.

Categories

Resources