I am trying to hide bottomTabbar when I onPress a botton.
In my App.js file I have my ButtomTabNavigator :
const ButtomTabNavigator = createBottomTabNavigator(
{
screenOne: {
screen: RealReviewMain,
navigationOptions: ({ navigation }) => ({
tabBarVisible: true,
})
},
screenTwo: {
screen: RealReviewMain,
//Here I set the tabbarVisible to true
navigationOptions: ({ navigation }) => ({
tabBarVisible: true,
})
},
},
)
From ScreenTwo, I try to hide bottom tabbar using onPress
<TouchableOpacity
onPress={()=> {
this.props.navigation.setParams({ tabBarVisible: false });
}}/>
Is this the right way to do it? nothing happens.
Any advice or comment would be really appreciated! Thanks in advance!
It's possible to hide/show a tabBar based off button press. Using static navigationOptions. An example would be:
static navigationOptions = ({ navigation }) => {
return {tabBarVisible: navigation.state.params.tabBarVisible}
}
This is a simple example, you would need to initialize tabBarVisible since it would be false. A full component could look like:
import React, { Component } from 'react'
import { Text, View, Button } from 'react-native'
class Screen extends Component {
componentDidMount = () => {
this.props.navigation.setParams({ tabBarVisible: true }) //initialize the state
}
static navigationOptions = ({ navigation }) => {
return {tabBarVisible:navigation.state.params && navigation.state.params.tabBarVisible}
}
render() {
return (
<View style={{flex:1}}>
<Button title={"hide"} onPress={() => this.props.navigation.setParams({tabBarVisible:false})}/>
<Button title={"show"} onPress={() => this.props.navigation.setParams({tabBarVisible:true})}/>
</View>
)
}
}
export default Screen
As far as i know, you cannot hide navigation elements once they are rendered in the page.
But, as stated here you can hide navigation elements in specific screens as follows:
const FeedStack = createStackNavigator({
FeedHome: FeedScreen,
Details: DetailsScreen,
});
FeedStack.navigationOptions = ({ navigation }) => {
let tabBarVisible = true;
if (navigation.state.index > 0) {
tabBarVisible = false;
}
return {
tabBarVisible,
};
};
If you want to hide the navigator in a specific screen you can add an if condition:
if (navigation.state.index > 0 && navigation.state.routes[1].routeName === "<name of the screen>")
Related
I have BottomTabNavigator with 4 tabs I have the structure as in the screenshot below. That is the View below the BottomTabBar which is achieved but, the problem is I am not able to navigate from the Home/search tab to any other tab. Also, I tried with passing navigation in <Appcontainer /> as given below in the code but it is also not working.
I am using react-navigation v3.11.2
Is there any other way to pass navigation prop in <Appcontainer />. Or Any other method so I can able to navigate in BootomTabs.
const Tabs = createBottomTabNavigator(
{
Home: {
screen: Home,
},
Search: {
screen: Search,
},
Add: {
screen: () => null,
navigationOptions: () => ({
tabBarOnPress: async ({ navigation }) => {
navigation.navigate('Upload');
}
}),
},
Profile: {
screen: Profile,
},
},
);
export default class ParentTabs extends React.Component {
render() {
const { navigate } = this.props;
return (
<View>
<AppContainer navigate={navigate} />
<View>
<Text>My Text</Text>
</View>
</View>
);
}
}
const AppContainer = createAppContainer(Tabs);
navigation.navigate('Upload');
You cannot navigate to any random component. Upload should be a route name defined in your tab navigator.
Otherwise, you need to trigger Upload logic inside your Add screen
I used createMaterialTopTabNavigator to create footer tab, like as below:
const TabNavigator = createMaterialTopTabNavigator(
{
HomeScreen: HomeScreen,
UserScreen: UserScreen,
},
{
initialRouteName: 'HomeScreen',
navigationOptions: {
header: null,
},
tabBarPosition: 'bottom',
tabBarComponent: FooterTabs,
},
);
and in FooterTabs on home screen button, i have this code:
if (this.props.navigation.state.index === 0) {
// i want call scrollToUp function in HomeScreen component
}
i want when user is in HomeScreen and press on home button react call scrollToUp method in HomeScreen.
===== resolved:
I added this code to HomeScreen:
componentDidMount() {
this.props.navigation.setParams({
onFocus: this.scrollToUp,
});
}
and edit FooterTabs like as below:
if (this.props.navigation.state.index === 0) {
this.props.navigation.state.routes[0].params.onFocus();
}
Hav you trid putting your Homescreen in a scrollView , and when the user presses home button ,
class HomeScreen extends Component {
render(){
return(
< ScrollView ref={(ref) => { this.scrollListReftop = ref; }}>
// your code here
< /ScrollView>
)
}
}
// add this to scroll to the top of scrollView inside your componentDidMount of Homescreen
componentDidMount(){
setTimeout(() =>this.scrollListReftop.scrollTo({x: 0, y: 0, animated: true}),10);
}
Hope its clear, feel free for any doubts.
I want add button in react-native header , the button is to mas and unmask password in the page, the problem on click when i change the state to change secureTextEntry value, the icon wont change will keep as the initial value;
the function is working fine but the icon cant change
this.state.secureTextEntry ? "eye" : "eye-slash"
this is the main code
class ChangePasswordScreen extends Component {
constructor(props) {
super(props);
this.state = {
newPassword: null,
currentPassword: null,
confirmPassword: null,
errors: [],
secureTextEntry: true
};
this.maskPassword = this.maskPassword.bind(this)
}
componentDidMount() {
this.props.navigation.setParams({
headerRight: ( < TouchableOpacity onPress = {
() => {
this.maskPassword();
}
} > < Icon style = {
styles.eyeIcon
}
name = {
this.state.secureTextEntry ? "eye" : "eye-slash"
}
size = {
20
}
color = {
Colors.WHITE
}
/></TouchableOpacity > )
})
}
static navigationOptions = ({
navigation
}) => {
return {
// headerTitle: <LogoTitle />,
headerRight: navigation.state.params && navigation.state.params.headerRight,
};
};
maskPassword = () => {
this.setState({
secureTextEntry: !this.state.secureTextEntry
})
}
}
Kinda late, might help someone nevertheless.
If you wish to add a button to the header of a screen, from the screen itself, not the App.js file and you are using a functional component, it goes like this:
import { useNavigation } from '#react-navigation/native'
export default function () {
const nav = useNavigation();
useEffect(() => {
nav.setOptions({
headerRight: () => <Button />,
});
}
}
The problem is this.setState will not re-render header component . if you want to change header right then you have to call setParams again
Try this code in componentDidMount
componentDidMount() {
this.props.navigation.setParams({
headerRight: this.setHeaderRight(this.state.secureTextEntry)
});
}
Set function for header right
setHeaderRight = state => {
//console.log("setHeaderRight", this.state.secureTextEntry);
return (
<TouchableOpacity
onPress={() => {
this.maskPassword();
}}
>
<Icon
style={styles.eyeIcon}
name={state ? "eye" : "eye-slash"}
size={20}
color={Colors.WHITE}
/>
</TouchableOpacity>
);
};
Set header right again when state set
maskPassword = () => {
this.setState({
secureTextEntry: !this.state.secureTextEntry
});
this.props.navigation.setParams({
headerRight: this.setHeaderRight(!this.state.secureTextEntry)
});
};
You are setting a Component as a navigation param on Component mount and passing in a state value at the time the Component mounted.
This param never gets changed or updated again so the navigation header never gets re rendered.
A better way would be to pass the value of state directly as a navigation param and use that in the component that is used directly in the navigationOptions
i'm new in react native. i want to add if condition in initialRouteName like code below. when "notification" variable is null move to "MemberProfile" page. but if "notification" variable is not null move to "ReviewMember" page. i try it code but still move to "MemberProfile" page. any solution?.
this is my code
var notification = null;
class DrawerMember extends Component {
constructor(props) {
super(props);
this.state = {
notifData: null
};
this.callCheck();
}
async callCheck() {
await AsyncStorage.getItem("#tryCode:notification", (err, result) => {
if (result != null) {
this.setState({
notifData: "testing data"
});
}
});
}
render() {
notification = this.state.notifData;
return <Root />;
}
}
const Root = createDrawerNavigator(
{
MemberProfile: {
screen: MemberProfileScreen
},
ReviewMember: {
screen: ReviewScreen
}
},
{
drawerPosition: "right",
initialRouteName: notification == null ? "MemberProfile" : "ReviewMember",
contentComponent: props => <SideBar {...props} />,
}
);
export default DrawerMember;
I think Root is created before the async function returns so notification is always null.
A possible way to solve this problem would be to use a SwitchNavigator as the first screen in your drawer. This navigator would be responsible for loading the notification and redirecting to the right screen.
Something along the lines of:
import React from 'react';
import { View, AsyncStorage, ActivityIndicator, StatusBar } from 'react-native';
export default class DummySwitch extends React.Component {
async componentDidMount() {
this.listener = this.props.navigation.addListener('willFocus', async () => {
const notification = await AsyncStorage.getItem('#tryCode:notification');
if (notification === null) {
this.props.navigation.navigate('MemberProfile');
}
else {
this.props.navigation.navigate('ReviewMember');
}
});
}
render() {
return (
<View>
<ActivityIndicator />
<StatusBar barStyle='default' />
</View>
);
}
}
As you can see, the switch screen just displays a loading button while accessing the async storage and deciding which route to take.
Then you define the drawer as usual but you add the switch screen as the initial route. You can also hide the label if you want by defining your own drawerLabel:
export default createDrawerNavigator({
Switch: {
screen: Switch,
navigationOptions: () => ({
drawerLabel: () => null,
}),
},
MemberProfile: {
screen: MemberProfileScreen,
},
ReviewMember: {
screen: ReviewScreen,
},
}, { initialRouteName: 'Switch' });
This is it, the drawer now selects the route based on your async storage.
I have a button in header to open & close navigation drawer menu.
When I call below method from componentDidMount() it worked and opened the menu:
this.props.navigation.toggleDrawer();
But when I click the button it didn't work and just fade the screen!
Here is the component code :
export class Home extends BaseScreen {
constructor(props) {
super(props);
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return ({
headerStyle: {
backgroundColor: '#FF9800'
}
, headerRight: <UserCoins />
, headerLeft: <Button onPress={params.handlePress} title='Menu' />
, title: 'title'
})
}
_handlePress() {
this.props.navigation.toggleDrawer();
}
state = {
coins: 0,
}
//
componentDidMount() {
this.props.navigation.setParams({
handlePress: this._handlePress.bind(this)
});
//here working
this.props.navigation.toggleDrawer();
}
render() {
return (<Text />);
}
}
export default Home
My navigator structure is :
1.SwitchNavigator
2.BottomTabNavigator
3.DrawerNavigator
4.StackNavigator (Home component inside it)
You can call 'navigation' that you are passing into your static NavigationOptions rather than trying to bind it in the params for navigation.
Try this on your onPress Event for your button
onPress={() => navigation.navigate('DrawerToggle')}