React Native - When I open a new screen, the bottom tab navigator is dismissed but screen page is not full height - react-native

Lets say I am in the tab - ChatStack and I am on the screen stack - AllChatRooms. Then when I click on one of the chat rows, I am then navigated to the chat room. I have it coded that, when in the ChatRoom screen, don't display nav bar and that works. But the ChatRoom screen does not reach full height and it acts like the nav bar is still there. I attached an image with colors so you can see what I am talking about.
Would really appreciate some help if anyone knows how to get the screen to reach the bottom of the phone screen.
So I am using a bottom tab navigator like this (simplified version):
Tabs.js
const getRouteName = (route) => {
const routeName = getFocusedRouteNameFromRoute(route);
if (routeName?.includes("HomeAllCategories") || routeName === "ChatRoom") {
return "none";
}
return "flex";
}
return (
<Tab.Navigator screenOptions={{ tabBarShowLabel: false }}>
<Tab.Screen name="Home" component={HomeStack}/>
<Tab.Screen name="Bookmarks" component={BookmarkStack}/>
<Tab.Screen name="Chats" component={ChatStack} options={({route}) => ({
tabBarStyle: {display: getRouteName(route)},
})}/>
<Tab.Screen name="Settings" component={SettingsStack}/>
</Tab.Navigator>
)
ChatStack.js
<Stack.Navigator>
<Stack.Screen name="AllChatRooms" component={AllChatRooms} />
<Stack.Screen name="ChatRoom" component={ChatRoom} />
</Stack.Navigator>
ChatRoom.js
return (
<SafeAreaView className="flex-1 bg-slate-900">
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
className="flex-1"
keyboardVerticalOffset={10}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<FlatList
data={messages}
className="pl-4"
keyExtractor={item => item.id}
renderItem={({ item }) =>
item.from === user.name ? (
<ReceiverMessage message={item} />
) : (
<SenderMessage message={item} />
)
}
/>
</TouchableWithoutFeedback>
{/* Text Box */}
<View className="bg-white flex-row justify-between items-center border border-gray-200 px-5 py-2">
<TextInput
className="h-10 text-lg w-4/5"
placeholder="Send Message..."
/>
<Button title="Send" color="#6ECCAF"/>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
)
and I'm using:
"#react-navigation/bottom-tabs": "^6.5.2",
"#react-navigation/native": "^6.1.1",
"#react-navigation/native-stack": "^6.9.7",
But sometimes it does have the full height and I don't know why? On launch, the height of the screen is never working but after leaving and opening the chat room several times, the height of the screen does reach the bottom. Why is that?

Related

How do i skip the animation only replace with react-navigation

i am using #react-navigation/stack^5.14.4 and #react-navigation/native^5.9.4, to handle the scene transition between Home, Login and Profile pages.
there are 2 transition cases i need to handle:
Home -> Profile (should have animation enabled)
Login -> Profile (need to skip the animation)
the reason why to skip the animation is that I am using a loading skeleton similar to the layout of Profile page during the login process. It is weird to have a transition between the profile page content and the skeleton itself. However I want to keep the awesome animation if pushed from Home page.
Is there a simple solution like
navigation.replace("Profile"); // with animation
navigation.replace("Profile", { animationEnabled: false }); // skip animation
You can use options to get the route property and check weather there is any parameter to disable the screen
snak: https://snack.expo.dev/#ashwith00/react-navigation-5-boilerplate
heres is an example
function TestScreen({ navigation }) {
return (
<View style={styles.content}>
<Button
mode="contained"
onPress={() => navigation.push('Test1', {disabledAnimation: true})}
style={styles.button}>
Push screen Without Animation
</Button>
<Button
mode="contained"
onPress={() => navigation.push('Test1')}
style={styles.button}>
Push new screen
</Button>
{navigation.canGoBack() ? (
<Button
mode="outlined"
onPress={() => navigation.pop()}
style={styles.button}>
Go back
</Button>
) : null}
</View>
);
}
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Test"
component={TestScreen}
options={{ title: 'Custom animation' }}
/>
<Stack.Screen
name="Test1"
component={TestScreen}
options={({ route }) => ({
title: 'Custom animation',
cardStyleInterpolator: !route.params?.disabledAnimation
? undefined
: CardStyleInterpolators.forNoAnimation,
})}
/>
</Stack.Navigator>
);
}
i find a more simple way to make it:
firstly, export the Stack.Screen node from the router file.
export const ProfileStack = (
<Stack.Screen name={'Profile'} component={Profile} />
);
export default Router = () => (
<Stack.Navigator>
<Stack.Screen name={'Home'} component={Home} />
<Stack.Screen name={'Login'} component={Login} />
{ProfileStack}
</Stack.Navigator>
);
then I can execute like this to disable the animation once.
with animation:
<Button onClick={() => {
navigation.replace('Profile');
}} />
without animation
<Button onClick={() => {
ProfileStack.props.options.animationEnabled = false;
navigation.replace('Profile');
ProfileStack.props.options.animationEnabled = true;
}} />

How to include two buttons at headerLeft position?

I have been trying to include two icon buttons at headerLeft position but only one icon button appears at the position. I have mentioned my code below which has no errors. Using the code, I am unable to obtain the desired output that is only one of the two icon buttons is appearing at the headerLeft position. I have created AccountStack using createStackNavigator(). At the headerRight position hamburger icon appears to access the drawer. I want settings icon button and help icon button to appear at the headerLeft position together.
export default function AccountStack({navigation}) {
return (
<Stack.Navigator>
<Stack.Screen name="Account" component= {AccountScreen}
options={{headerRight: () => (<Ionicons.Button name="reorder-three" color={"#FF0000"} size={32} onPress={() => navigation.openDrawer()}/>),
headerLeft: ()=> ( <Ionicons.Button name= "settings" color={"#FF0000"} size={32}/> ,
<Ionicons.Button name= "md-help-circle" color={"#FF0000"} size={32}/> )}}/>
<Stack.Screen
name="Help"
component= {HelpScreen}
options={{headerRight: () => (<Ionicons.Button name="reorder-three" color={"#FF0000"} size={32} onPress={() => navigation.openDrawer()}/> ) }}/>
<Stack.Screen
name="Settings"
component= {SettingScreen}
options={{headerRight: () => (<Ionicons.Button name="reorder-three" color={"#FF0000"} size={32} onPress={() => navigation.openDrawer()}/> ) }}/>
</Stack.Navigator>
);
}
I am a beginner, kindly help me out in resolving the problem.
You can only render a single component in the headerLeft, therefore you need to wrap the two icons you want to set in a View
(Just for you to know: you can also build a more complex component to render in the headerLeft, with multiple buttons/texts etc)
<View>
<Ionicons.Button name= "settings" color={"#FF0000"} size={32}/> ,
<Ionicons.Button name= "md-help-circle" color={"#FF0000"} size={32}/>
</View>

Tab navigation lag when nested in drawer

I am having a issue when I am nesting my Tabs within my Drawer. Unfortunately, navigating to each tab is very slow, and their seems to be a lot of lag.
However, when I remove the Drawer navigator, and make it so that their is only a tab navigator, navigating between the different tab screens is noticeably better.
How can I make it so that their is no delay between the tabs when the tabs are nested in to the drawer?
{ *
With help from Mateusz, I have managed to pinpoint the issue. I tested the delay by rendering four of the same components. The first test was using
children={() => {
return <NfcWifiConfig />;
}}
And the delay was still there
But then, when I used
component={NfcWifiConfig}
The delay is completely gone and navigation is running smoothly as it should. So my question now is, where do i go from here? How would i pass the props down with this syntax?
}
My current code is:
const DrawerComponent = ({
Bunch of props here
}) => {
return (
<Drawer.Navigator
drawerType="back"
drawerContent={(props) => {
return (
<DrawerContent
{...props}
/>
);
}}
>
{/* TABS */}
<Drawer.Screen
name="MainHome"
children={({navigation}) => {
return (
<>
<StatusBar backgroundColor={homeColor} barStyle="dark-content" />
<Navbar navigation={navigation} userimage={userimage} />
<Tabs.Navigator>
{/* HOME STACK */}
<Tabs.Screen
name="Profile"
children={() => {
return (
<>
<MainStackNavigator
{Bunch of props here}
/>
</>
;
}}
/>
{/* SEARCH SCREEN */}
<Tabs.Screen
name="Search"
children={() => {
return (
<>
<StatusBar barStyle="dark-content" />
<SearchStack
{ Bunch of props here }
/>
</>
);
}}
/>
{/* NFC-SOCIAL SCREEN */}
<Tabs.Screen name="Activate" component={NfcConfig} />
{/* NFC-WIFI SCREEN */}
<Tabs.Screen name="WiFi" component={NfcWifiConfig} />
</Tabs.Navigator>
</>
);
}}
/>
{/* Add Links Screen */}
<Drawer.Screen
name="Add Links"
children={({navigation}) => {
return (
<AddLinksScreen
{ Bunch of props here }
/>
);
}}
/>
{/* Following Screen */}
<Drawer.Screen
name="Followers"
children={({navigation}) => {
return (
<FollowerStack
{ Bunch of props here }
/>
);
}}
/>
{/* Following Screen */}
<Drawer.Screen
name="Following"
children={({navigation}) => {
return (
<FollowingStack
{ Bunch of props here }
/>
);
}}
/>
</Drawer.Navigator>
);
};
Also, the add links screen and followers/following screens work fine. Navigating to them works efficiently with no lag. But the tabs => home stack, search screen and the other two, have a heavy delay when navigating between them.
In terms of the content inside the tabs, the last two tabs are very light, and do not contain much content. I have tried commenting out the heavy tab screens and using just the two lightweight components, but same result. Making me believe that is not the issue.
So I managed to fix the issue. When I used:
children={() => {
return <NfcWifiConfig props{props} />;
}}
The lag was present. However, when I used:
component={NfcWifiConfig}
The lag disappeared. However, my props were not being passed through. So what I did was use React Context to pass my props to all the different components that needed it and that's it, the lag was gone and the components were receiving the props as I wanted.
Also, the code is a lot cleaner when using React context, so I highly recommend it.

Facing issue when trying to add image on bottom tab navigation in react-native

When i am trying to adding image in bottom tab navigation then i just got only title of bottom tab.
How i can get image in bottom tab navigation in react-native?
I am using
import { NavigationContainer } from "#react-navigation/native"
import { createStackNavigator } from "#react-navigation/stack"
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs"
//this libraries for achieve bottom tab navigation in react native.
function TabNav() {
return (
<Tab.Navigator
initialRouteName="Logbook"
tabBarOptions={{
activeTintColor: "#3498db",
}}
>
<Tab.Screen
name="Logbook"
component={Logbook}
options={{
tabBarLabel: 'Logbook',
tabBarIcon:({focused})=>{
focused?
<Image source={Images.logbookImg} style={styles.activeImg} />
: <Image source={Images.logbookImg} style={styles.deActiveImg} />
}
}}
/>
<Tab.Screen
name="Voyage"
component={Voyage}
options={{
tabBarLabel: 'Voyage',
tabBarIcon:({focused})=>{
focused?
<Image source={Images.voyageImg} style={styles.activeImg} />
: <Image source={Images.voyageImg} style={styles.deActiveImg} />
}
}}
/>
<Tab.Screen
component={Crew}
name="Crew"
options={{
tabBarLabel: 'Crew',
tabBarIcon:({focused})=>{
focused?
<Image source={Images.crewImg} style={styles.activeImg} />
: <Image source={Images.crewImg} style={styles.deActiveImg} />
}
}}
/>
</Tab.Navigator>
)
The problem is very simple, you are not returning the image
tabBarIcon:({focused})=>(
focused?
<Image source={Images.logbookImg} style={styles.activeImg} />
: <Image source={Images.logbookImg} style={styles.deActiveImg} />
)
replace the curly braces with brackets or put a return statement and it would work as expected.

Adding a back button for each bottom tab with React Navigation

The bottom tabs navigation is looking something like that:
const Tab = createBottomTabNavigator();
export default function TabStackScreen() {
return (
<Tab.Navigator initialRouteName="Home">
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Favorites" component={FavoritesStackScreen} />
<Tab.Screen name="Search" component={SearchStackScreen} />
</Tab.Navigator>
)
}
There is not back button on the favorites and search screen. I guess this is the normal behavior, but I would love to have one.
I did not find something relevant in the doc, except recreating a component that looks like the native back button and adding it on some screens using headerLeft. Is there a more simple method?
In my projects I like to create custom headers, and I do not show the default header and show my own custom header component.
On my custom component I add right and left components, and let the screens decide what to do, by default the back button is shown, but if the screen pass the noBack property, the button is hidden.
You can also add a right component, for example a close button.
That is what I use to do:
const screenOptions = {
headerShown: false
};
<RootStack.Navigator screenOptions={screenOptions} mode="modal">
and then create my own component
export const Header = ({ title, leftComponent, rightComponent, noBack }) => {
const navigation = useNavigation();
return (
<Wrapper>
{leftComponent ||
(noBack ? (
<Placeholder />
) : (
<Button
onPress={() => navigation.goBack()}
accessible
accessibilityRole="button"
accessibilityLabel="Back">
<Icon
size={30}
name={Platform.OS === 'android' ? 'arrow-left' : 'chevron-left'}
/>
</Button>
))}
<Title bold accessibilityRole="header" acessible acessibilityText={title}>
{title}
</Title>
{rightComponent || <Placeholder />}
</Wrapper>
);
};
Doing that, you are able to customize everything on your header, it works like a charm for me.