react-native-navigation: how to hide bottomTabs when keyboard is shown? - react-native

I am using the bottomTabs navigator from react-native-navigaton to navigation within my app. However, each time I have for example a TextInput field, the bottomTabs are being pushed up.
What is a possible way to hide the bottomTabs whenever the keyboard is being shown?

just add tabBarHideOnKeyboard: true to screenOptions

Add the following to your android manifest in android/app/src/AndroidManifest.xml
in your activity tag add/replace this attribute
the bottom tab should be hidden now.
android:windowSoftInputMode="stateUnspecified|adjustPan"

You can programmatically hide the bottom tab when the keyboard is open using React hooks
const _keyboardDidShow = useCallback(() => {
navigation.setOptions({
tabBarVisible: false,
});
}, [navigation]);
const _keyboardDidHide = useCallback(() => {
navigation.setOptions({
tabBarVisible: true,
});
}, [navigation]);
useEffect(() => {
Keyboard.addListener('keyboardDidShow', _keyboardDidShow);
Keyboard.addListener('keyboardDidHide', _keyboardDidHide);
// cleanup function
return () => {
Keyboard.removeListener('keyboardDidShow', _keyboardDidShow);
Keyboard.removeListener('keyboardDidHide', _keyboardDidHide);
};
}, [_keyboardDidHide, _keyboardDidShow]);

Answer for React Navigation V6 with or without a Custom tabBar
I'm using react navigation V6 since i'm using a custom tabBar the tabBarHideOnKeyboard: true prop not working but when i change the custom tabBar to default tab bar that prop works but i don't like the behavior of that prop on android, so i used keyboard from react-native to check if the keyboard is active or not and setting the css display prop to 'none'
import { Keyboard, View } from "react-native";
const [keyboardStatus, setKeyboardStatus] = useState<boolean>();
useEffect(() => {
const showSubscription = Keyboard.addListener('keyboardDidShow', () => {
setKeyboardStatus(true);
});
const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
setKeyboardStatus(false);
});
return () => {
showSubscription.remove();
hideSubscription.remove();
};
}, []);
so on the custom tab bar component now we can do like this.
<View style={
[
styles.mainContainer,
keyboardStatus ? styles.hideTabNavigation : null,
]
}
>
// your code here
</View>
Hope this will help someone until they fix this issue!

Related

Navigation v5 React Native

I have some question on React Native Navigations v5
I have a sub function in my main function. I also have screenOption = (navData) function for customise my navigation and have few header button here which out of my Main function. My Problem now i am not sure how to access the subFunction that located in my mainfunction from my screenOption = (navData). For example whenclick the icon on the header Button and it will trigger the dispatch function to store which located inside the main function.
const mainfunction = (props) =>{
subfunction = async(data) =>{
dispatch(action.delete(data)
}
return ()
}
export const screenOptions = (navData) => {
Item
title="Delete"
iconName={
Platform.OS === "android" ? "md-create" : "ios-trash-outline"
}
onPress={() => {
trigger subfunction here
}}
/>
}
Try creating a custom button and add the component using setOptions
React.useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => <CustomHeaderButton onPress={customOnPress} />
});
}, []);

How do I update react-native component, when click on tab on bottom Tab Navigator

I am using bottom tab navigator in React-native for Navigation. When I switches tab, component are not updating.
Pls let me know how can I update/refresh whole component when I tap on tab at bottom Tab Navigator
Here is a simple solution.
import { useFocusEffect } from '#react-navigation/native';
useFocusEffect(
React.useCallback(() => {
console.log("Function Call on TAb change")
}, [])
);
Here is the link you can read more. https://reactnavigation.org/docs/function-after-focusing-screen/
You can use Navigation listener check Navigation Events, when screen gets focused it will trigger a function like this:
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
//Your refresh code gets here
});
return () => {
unsubscribe();
};
}, [navigation]);
And class component like this:
componentDidMount() {
this._unsubscribe = navigation.addListener('focus', () => {
//Your refresh code gets here
});
}
componentWillUnmount() {
this._unsubscribe();
}
If you want to force update check this question

how can I refresh screen that in drawer navigation when focused react native expo

I navigate by drawer to screen with Id and this Id not changed
export default function ScreenPage({ route, navigation }) {
useFocusEffect(
React.useCallback(() => {
Alert.alert(route.params.id);
return () => {
Alert.alert(route.params.id);
};
}, [])
);
return (<View/>)
}
The Id not changed all the time till I refresh the source code
I found solution to use
import { useIsFocused } from "#react-navigation/native";
export default function Details({ route, navigation }) {
const isFocused = useIsFocused();
useEffect(() => {
fetchDetails()
}, [isFocused])
return(<View />)
}
then all data on the screen will be refresh every time I navigate to screen

Tab bar navigation without component screen render

Is there a way to press on tab bar and not render component screen? i have been passing null function but it still renders blank screen. i want that wherever you press it stays on home screen.
Add a listener to the Screen.
component={() => null}
listeners={() => ({
tabPress: (e) => {
e.preventDefault(); // Prevents navigation
// Your code here for when you press the tab
},
})}
You can avoid navigation to the screen by creating your custom tabBar component in which you can handle onPress to each tabBarComponent so you can avoid navigation and do some action instead. Take a closer look at the example from react-navigation documentation here:
https://reactnavigation.org/docs/bottom-tab-navigator/#tabbar
This line of code from the example should be helpful for you:
const onPress = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
};

How do we implement Scroll to top functionality on tapping of the corresponding tab button on a bottom tab navigator in react navigation?

The React Navigation version I am using is v5. In the ScrollView corresponding to a Bottom Tab Icon, if the user is already on that given screen, I want to enable functionality where the user scrolls to the top when this icon is pressed.
As stated in the documentation, this feature should be already implemented. But I think you have placed your ScrollView inside a nested StackNavigator, right?
In that case, you probably need to subscribe to TabNavigator event and fire your scrollToTop manually
React.useEffect(() => {
const unsubscribe = navigation.addListener('tabPress', e => {
// Get your scrollView ref and dispatch scrollToTop
});
return unsubscribe;
}, [navigation]);
Hope it'll help you!
None of the solutions worked for me on the web, not using listener and not using useScrollToTop which is provided by react-navigation. Because I have nested stacks and navigators and also custom tabbar.
I solved the problem by setting a navigation param for scrolling to the top.
I have custom tabbar, and I needed to scroll to top on the homepage which was the first route of the tab stack.
So, in the homepage I set the scrollToTop parameter for the navigator:
const homelistRef = React.useRef<FlatList | null>(null)
useFocusEffect(
useCallback(() => {
navigation.setParams({
scrollToTop: () => homelistRef.current?.scrollToOffset({ offset: 0, animated: true }),
});
}, [navigation, homelistRef]),
);
return (
<FlatList
ref={homelistRef}
...{other Flatlist configs}
/>
)
And in my Tabbar component, I read this new param and execute it in the onPress function of the tabs:
interface IProps extends BottomTabBarProps {}
const TabBar: React.FC<IProps> = ({ state, navigation }) => {
const handleTabPress = useCallback(
(route) => async () => {
const currentRoute = state.routes?.[state.index];
if (
route === currentRoute?.name &&
state.routes?.[0].state?.routes?.[0]?.params?.scrollToTop
) {
state.routes[0].state.routes[0].params.scrollToTop();
}
},
[navigation, state],
);
return (
{render tab component}
)
}
And that's the ultimate solution for executing some action on active tabs.