How can I hide links in my react navigation drawer? - react-native

so I have a react navigation drawer, I can't manage to find out how to hide links in my drawer.
I have several links to other screens but I don't want them all visible.
Here's my code :
const AppDrawerNavigator = createDrawerNavigator({
Home: drawer,
Play: PlayScreen,
Gall: Gallery,
PlayerInput: PlayerInput,
Cam: OpenCamera,
srollView: ScrollView,
Profil: Profil,
})
export default class HomeScreen extends React.Component {
render() {
return (
<View style={styles.full}>
<AppDrawerNavigator/>
</View>
);
}
}
const styles = StyleSheet.create({
full: {
flex: 1,
backgroundColor: '#458680',
flexDirection:'column'
},
});
Any idea ? thx !

Do the following changes in your code:
const AppDrawerNavigator = createDrawerNavigator({
Home: drawer,
Play: PlayScreen,
Gall: Gallery,
PlayerInput: PlayerInput,
Cam: OpenCamera,
srollView: ScrollView,
Profil: Profil,
},
{
contentComponent: DrawerContent,
}
)
const DrawerContent = (props) => (
<View>
<View
style={{
height: '100%',
backgroundColor: '#458680',
}}
>
//Your code here whatever you wanna display
</View>
<DrawerItems {...props} />
</View>
)

Related

Nested Stack Navigator and Drawer Navigator in React Native

I have a couple of issues with setup Stack Navigator and Drawer Navigator. First and foremost, the below picture is the flow that I expected and I followed the documentation provided by the React Navigation to implement but I have no luck to achieve what I expected and the output of the implementation looks so weird (You can find it on the 2nd picture). I also attached my code snippet at the bottom.
Also, the output looks like the Drawer navigator header is duplicated with the Stack Navigator.
Besides that, I am quite new to React Native. I hope someone makes me more clearer how the implementation should look like because I have come across few articles and websites, their solution does not work in my case.
P/S: Screen X is opened when one of item clicked from Screen C
import React, { Component } from 'react';
import {
Image,
Button,
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
StatusBar,
} from 'react-native';
import { createDrawerNavigator, DrawerActions, DrawerItems } from 'react-navigation-drawer';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import HomeScreen from '../HomeScreen';
import ItemDetailScreen from '../ItemDetailScreen';
import ProfileScreen from '../ProfileScreen';
const navOptionsHandler = (navigation) => {
header: null
}
const CustomDrawerComponent = (props) => (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ height: 150, backgroundColor: 'white', alignItems: 'center' }}>
<Image source={{ uri: 'https://example.com/logo.png' }} style={{
height: 120,
width: 120,
borderRadius: 60
}} />
</View>
<ScrollView>
<DrawerItems {...props} />
</ScrollView>
</SafeAreaView>
)
const MyDrawerNavigator = createDrawerNavigator(
{
Home: {
screen: HomeScreen
},
Profile: {
screen: ProfileScreen
}
},
{
initialRouteName: "Home",
contentComponent: CustomDrawerComponent,
contentOptions: {
activeTintColor: 'orange'
}
}
);
const MyStackNavigator = createStackNavigator(
{
HomeA: {
screen: MyDrawerNavigator
},
ItemDetail: {
screen: ItemDetailScreen,
navigationOptions: navOptionsHandler
}
},
{
initialRouteName: "HomeA"
}
);
const AppContainer = createAppContainer(MyStackNavigator);
export default class StackNavigator extends Component {
render() {
return <AppContainer />;
}
}
Your drawer navigator is encapsulated by the stack navigator, which is why you have a double header.
What you need to do is to have the drawer navigator as your main navigator, and have your stack navigator as your profile screen, so it will be displayed as you click on "Profile" in your drawer navigator.
This should work:
const navOptionsHandler = navigation => {
null
}
const CustomDrawerComponent = props => (
<SafeAreaView style={{ flex: 1 }}>
<View
style={{ height: 150, backgroundColor: 'white', alignItems: 'center' }}
>
<Image
source={{ uri: 'https://example.com/logo.png' }}
style={{
height: 120,
width: 120,
borderRadius: 60,
}}
/>
</View>
<ScrollView>
<DrawerItems {...props} />
</ScrollView>
</SafeAreaView>
)
const MyStackNavigator = createStackNavigator(
{
Profile: ProfileScreen,
ItemDetail: {
screen: ItemDetailScreen,
navigationOptions: navOptionsHandler,
},
},
{
initialRouteName: 'Profile',
},
)
const MyDrawerNavigator = createDrawerNavigator(
{
Home: HomeScreen,
ProfileStack: {
screen: MyStackNavigator,
navigationOptions: () => ({
title: 'Profile',
}),
}
},
{
initialRouteName: 'Home',
contentComponent: CustomDrawerComponent,
contentOptions: {
activeTintColor: 'orange',
},
},
)
const AppContainer = createAppContainer(MyDrawerNavigator)
export default class StackNavigator extends Component {
render() {
return <AppContainer />
}
}
By the way since you say you are only just starting using React Native, unless you have a specific reason to use React Navigation v4, you should probably use v5 instead as v4 will become obsolete one day or another.

Complex React Navigation states

I want to use React Navigation in my React Native app, but I'm not sure how to get this specific functionality:
Demo from Samsung Health, where there is a bottom tab navigator, and in each tab screen there is a menu button in the header that opens a drawer navigator, and each option in the drawer navigator opens a stack navigator (which is the same for all tabs, i.e. the Home tab "For you" button opens the exact same "For you" screen as the Together tab and so on)
I've tried various combinations of stackNavigator, drawerNavigator, and bottomTabNavigator, but none behave in a sensible way, or at least in the way I wanted. I've made a basic bottomTabNavigator, but I don't know where to put the drawerNavigator in there;
const HomeStack = createStackNavigator({
Home: HomeScreen
});
const NotifyStack = createStackNavigator({
Notify: NotifyScreen
});
const ProfileStack = createStackNavigator({
Profile: ProfileScreen
});
const SettingsStack = createStackNavigator({
Settings: SettingsScreen
});
const DrawerStack1 = createStackNavigator({
DrawerStack: DrawerScreen1
});
const DrawerStack2= createStackNavigator({
DrawerStack: DrawerScreen2
});
const DrawerStack3 = createStackNavigator({
DrawerStack: DrawerScreen3
});
const Drawer = createDrawerNavigator({
DrawerStack1,
DrawerStack2,
DrawerStack3
});
const AppBottomTabs = createMaterialBottomTabNavigator({
Home: HomeStack,
Notify: NotifyStack,
Profile: ProfileStack,
Settings: SettingsStack
});
I have created sample project for you which have 3 tabs and drawer in each tab . Drawer have options(Events,ForYou) which will open separate screen
App Demo
Complete Sample Code
import React from 'react';
import {View, Text, Image, TouchableOpacity} from 'react-native';
import {createAppContainer} from 'react-navigation';
import {createDrawerNavigator} from 'react-navigation-drawer';
import {createStackNavigator} from 'react-navigation-stack';
import {createBottomTabNavigator} from 'react-navigation-tabs';
/*
Components
*/
class HomeScreen extends React.Component {
render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Home!</Text>
</View>
);
}
}
class Together extends React.Component {
render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Together</Text>
</View>
);
}
}
class Discover extends React.Component {
render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Discover</Text>
</View>
);
}
}
class Events extends React.Component {
render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Events</Text>
</View>
);
}
}
class ForYou extends React.Component {
render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>ForYou</Text>
</View>
);
}
}
class DrawerComponent extends React.Component {
drawerOptions = [
{title: 'For you', route: 'ForYou'},
{title: 'Events', route: 'Events'},
];
render() {
return (
<View style={{flex: 1, marginTop: 60}}>
{this.drawerOptions.map(item => (
<TouchableOpacity
style={{padding: 16}}
onPress={() => {
this.props.navigation.toggleDrawer();
this.props.navigation.navigate(item.route);
}}
key={item.title}>
<Text>{item.title}</Text>
</TouchableOpacity>
))}
</View>
);
}
}
/*
Navigator
*/
const TabNavigator = createStackNavigator(
{
TabsStack: {
screen: createBottomTabNavigator({
HomeScreen,
Together,
Discover,
}),
},
},
{
defaultNavigationOptions: ({navigation}) => ({
title: 'SamSung Health',
headerLeft: (
<TouchableOpacity
style={{padding: 16}}
onPress={() => navigation.toggleDrawer()}>
<Image
source={require('./drawer.png')}
style={{width: 30, height: 30}}
/>
</TouchableOpacity>
),
}),
},
);
const DrawerNavigator = createDrawerNavigator(
{
Home: {
screen: TabNavigator,
},
},
{drawerType: 'slide', contentComponent: DrawerComponent},
);
DrawerNavigator.navigationOptions = {
header: null,
};
const AppNavigator = createStackNavigator({
Home: {
screen: DrawerNavigator,
},
Events,
ForYou,
});
const AppContainer = createAppContainer(AppNavigator);
// render App Component
export default class App extends React.Component {
render() {
return (
<View style={{flex: 1}}>
<AppContainer />
</View>
);
}
}
Snack Link : https://snack.expo.io/#mehran.khan/3d6749 (please check in Android/IOS)

TabNavigator not switching tabs. navigation.navigate is not a function

I just started a new project and added a TabNavigator. when i tap on either of the tabs, i get a red error stating:
"navigation.navigate is not a function(In 'navigation/navigate(navigateion.state.routes[index].routeName', 'navigation.navigate' is undefined)"
If I change the initial route, each tab will show correctly on screen, as well as highlight the correct tab on the bottom of the screen.
export default TabNavigator(
{
Home: { screen: HomeScreen },
Card: { screen: CardScreen },
Schedule: { screen: ScheduleScreen },
},
{
initialRouteName: 'Home',
}
);
Downgrading React-navigation from 2.0.0 down to 1.0.3 solves the issue.
This is what I am using to change the Tab.
This is the defination of my customeTab
const customeTab = ({ navigation }) => {
Below is the code to naviagate:
const routes = navigation.state.routes;
{routes.map((route, index) => {
return (
<TouchableOpacity
activeOpacity={1.0}
onPress={() => {
navigation.navigate(route.key);
}
}
style={styles.tab}
key={route.key}
>
// do you stuff to show title and image.
</TouchableOpacity>);
})
}
I thought the problem is in your navigation.
import { TabNavigator } from 'react-navigation';
import HomeScreen from "./Home"
import SettingsScreen from "./Settings"
export default TabNavigator({
Home: { screen: HomeScreen },
Settings: { screen: SettingsScreen },
});
If you want to shift one page to another page you have to use navigation method.
Jumping between tabs
Switching from one tab to another has a familiar API — this.props.navigation.navigate.
import { Button, Text, View } from 'react-native';
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
<Button
title="Go to Settings"
onPress={() => this.props.navigation.navigate('Settings')}
/>
</View>
);
}
}
class SettingsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
</View>
);
}
}
Click this link. This is a official doc that will help you.

Can't navigate to other screen from the screen in TabNavigator

I trying to render StackNavigator inside TabNavigator. The Tabs are working fine, but i cannot link the button
In simple words, there's a button inside the "Feed" section of the TabNavigator "Tabs" . When clicked on the button, it should go to "UserDetails.js" via StackNavigator.
Please help!
Here is my index.android.js
export default class HackernoonNavigation extends Component {
render() {
return (
<Tabs />
);
}
}
export const Tabs = TabNavigator({
Feed: {
screen: Feed,
},
Me: {
screen: Me,
},
});
And here is the file "Feed.js" , inside which there is a button that leads to "UserDetail.js"
export default class Feed extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to Feed!
</Text>
<Button
onPress={() => this.props.navigation.navigate('Details')}
title="User Details"
/>
</View>
);
}
}
export const FeedStack = StackNavigator({
Details: { screen: UserDetail },
});
You can do it by defining tabnavigator inside stacknavigator as screen like in this way -
const StackNaviApp = StackNavigator({
UserDetails: { screen: UserDetails},
Feed: {
screen: TabNavigator({
Feed: { screen: Feed},
Me: { screen: Me}
}, {
tabBarOptions: {
showIcon: true,
lazy: true,
activeTintColor: '#7567B1',
labelStyle: {
fontSize: 16,
fontWeight: '600'
}
}
})
}});
export default StackNaviApp;
Taking Feed & Me inside TabNavigator & UserDetails inside StackNavigator directly . For more detail you can refer the source code from here -
http://androidseekho.com/others/reactnative/switching-between-stack-navigator-to-tab-navigator/
So I have a ListView on a Tab Screen and when I click on the List Item its navigating to a component called QR Code. So when I click a List Item the camera will be opened in a new window with StackNavigator.... I show you my code down below. Maybe it helps you to find your fault.
import React, {
Component,
} from 'react';
import {
// AppRegistry,
// Dimensions,
ListView,
StyleSheet,
Text,
TouchableOpacity,
TouchableHighlight,
View,
AsyncStorage
} from 'react-native';
import { SwipeListView, SwipeRow } from 'react-native-swipe-list-view';
import moment from 'moment';
import{createStackNavigator} from 'react-navigation';
import { Icon } from 'react-native-elements'
import QrCode from '../components/QrCode';
class SwipeList extends Component {
static navigationOptions = {
title: 'Scanner auswählen',
headerTintColor: 'white',
headerStyle: {backgroundColor: '#444444'},
headerTitleStyle: { color: 'white' },
};
constructor(props) {
super(props);
this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
scannerAvailable:false,
listType: 'FlatList',
listViewData: this.ds,
}
...
goToQrCodeScreen=(scanner)=>{
this.props.navigation.navigate('QrCode',{
scannerName: scanner.scannerName,
scannerValidityEnd: scanner.scannerValidityEnd,
scannerId: scanner.scannerId,
dataMacroId: scanner.dataMacroId,
hash:scanner.hash,
requestKey: scanner.requestKey,
})
}
...
render() {
return (
<View style={styles.container}>
<View>
<SwipeListView
dataSource={this.state.listViewData}
renderRow={ data => (
<View >
<TouchableHighlight
onPress={()=>this.goToQrCodeScreen(data)}
style={styles.rowFront}
underlayColor={'#AAA'}>
<Text> <Text style={[styles.listItemName,styles.textBold] } >{data.scannerName} </Text>
<Text style={styles.listItemValid}> gültig bis {moment(data.scannerValidityEnd).format('DD.MM.YYYY')}</Text>
</Text>
</TouchableHighlight>
</View>
)}
renderHiddenRow={ (data, secId, rowId, rowMap) => (
<View style={styles.rowBack}>
<TouchableOpacity style={[styles.backRightBtn, styles.backRightBtnRight]} onPress={ _ => this.deleteRow(data.scannerId,rowMap, `${secId}${rowId}`) }>
<Icon
name='trash'
type='font-awesome'
color='white'/>
<Text style={styles.backTextWhite}>
Löschen</Text>
</TouchableOpacity>
</View>
)}
rightOpenValue={-100}
enableEmptySections={true}
/>
</View>
</View>
);
}
}
const StackNavigation = createStackNavigator(
{
SwipeList:SwipeList ,
QrCode:QrCode
},
{
initialRouteName: 'SwipeList',
}
);
export default StackNavigation;
I deleted the code you dont need. I call the method goToQrCodeScreen() to navigate.
My fault was that I dont exported the StackNavigator. Now its working.
you need to wrap your feed in another component :
const FeedStack = createStackNavigator();
function FeedWrapper() {
return (
<HomeStack.Navigator>
<FeedStack .Screen name="Feed" component={Feed} />
<FeedStack .Screen name="Details" component={Details} />
</HomeStack.Navigator>
);
}
see https://reactnavigation.org/docs/tab-based-navigation

How to navigate between screens from any js class that is not inside App.js in React Native

It's very easy to navigate from one screen to another that is inside App.js class. What I have done is made three classes : App.js, SearchList.js and Detail.js. But i am facing issue that how to navigate from searchList.js to Detail.js on click any view inside searchList.js class. Should i use StackNavigator again in searchList.js or declare all classes in App.js ?
App.js
import React from 'react';
import { Image,Button, View, Text ,StatusBar,StyleSheet,Platform,TouchableOpacity,ImageBackground,Picker,Alert,TouchableHighlight} from 'react-native';
import { StackNavigator,DrawerNavigator,DrawerItems } from 'react-navigation';
import {Constants} from "expo";
import SearchList from './classes/SearchList';
import Detail from './classes/Detail';
const DrawerContent = (props) => (
<View>
<View
style={{
backgroundColor: '#f50057',
height: 160,
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text style={{ color: 'white', fontSize: 30 }}>
Header
</Text>
</View>
<DrawerItems {...props} />
</View>
)
class HomeScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Image
source={require('./images/crown.png')}
style={[styles.icon, {tintColor: '#f50057'}]}
/>
),
};
constructor(){
super();
this.state={PickerValueHolder : ''}
}
GetSelectedPickerItem=()=>{
Alert.alert(this.state.PickerValueHolder);
}
render() {
return (
<ImageBackground source={require('./images/green.png')} style={styles.backgroundImage} >
<TouchableOpacity onPress={() =>this.props.navigation.navigate('DrawerOpen')}>
<Image
source={require('./images/menu-button.png')}
style={styles.imagesStyle}
/>
</TouchableOpacity>
<View style={styles.columnContainer}>
<TouchableHighlight style={styles.search} underlayColor='#fff' onPress={() => this.props.navigation.navigate('SearchList')}>
<Text style={styles.searchText}>Search Hotels</Text>
</TouchableHighlight>
</View>
</ImageBackground >
);
}
}
class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
const styles = StyleSheet.create({
backgroundImage: {
flex: 1,
width: null,
height: null,
marginTop: Constants.statusBarHeight,
},
search:{
marginTop:20,
paddingTop:15,
borderRadius:8,
borderColor: '#fff'
},
searchText:{
color:'#fff',
textAlign:'center',
}
// backgroundColor: '#ef473a', // app color
});
const HomeStack = StackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({ navigation }) => ({
header: null,
})
},
SearchList: { screen: SearchList },
Detail: { screen: Detail},
});
const RootStack = DrawerNavigator(
{
Home: {
screen: HomeStack,
},
DetailsScreen: {
screen: DetailsScreen,
},
},
{
initialRouteName: 'Home',
}
);
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
SearchList.js
import React, { Component } from 'react';
import { StyleSheet, Platform, View, ActivityIndicator, FlatList, Text, Image, Alert, YellowBox,ImageBackground } from 'react-native';
import { StackNavigator,} from 'react-navigation';
import Detail from './classes/Detail';
export default class SearchList extends Component {
constructor(props) {
super(props);
this.state = {isLoading: true}
YellowBox.ignoreWarnings([
'Warning: componentWillMount is deprecated',
'Warning: componentWillReceiveProps is deprecated',
]);
}
GetItem (flower_name) {
Alert.alert(flower_name);
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: .0,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
webCall=()=>{
return fetch('https://reactnativecode.000webhostapp.com/FlowersList.php')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
componentDidMount(){
this.webCall();
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<ActivityIndicator size="large" />
</View>
);
}
return (
<View style={styles.MainContainer}>
<FlatList
data={ this.state.dataSource }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item}) =>
<ImageBackground source= {{ uri: item.flower_image_url }} style={styles.imageView}
onPress={() => this.props.navigation.navigate('Detail')}>
</ImageBackground>
}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: 'center',
flex:1,
margin: 5,
marginTop: Constants.statusBarHeight , //(Platform.OS === 'ios') ? 20 : 14,
},
imageView: {
width: '100%',
height: 220 ,
margin: 7,
borderRadius : 40,
},
});
const HomeStack = StackNavigator({
Detail: { screen: Detail},
});
export default class App extends React.Component {
render() {
return <HomeStack />;
}
}
Any help would be appreciable.
To navigate to any screen you need to have a navigation object. Navigation object can be provided in two ways
By declaring it in StackNavigator
By explicitly passing it as a prop to some other screen
If you use the first approach, and you need to navigate from SecondScreen to ThirdScreen, both of your screens should be declared in the StackNavigator first, only then navigation will be successful.
If you are using any trivial component ( such as a modal box ) to navigate to another screen, all you need to do is pass the navigation props (this.props.navigation) to the modal box component and use the props to navigate to another screen. The only requirement here being, this.props.navigation should be available in the class where the modal box component is loaded.
EDIT
As requested, here is the snippet
const App = StackNavigator({
FirstScreen: { screen: FirstScreen},
SecondScreen: { screen: SecondScreen},
ThirdScreen: { screen: ThirdScreen}
})
export default App;
In your SecondScreen, declare an object const { navigate } = this.props.navigation; and on a button click, use this object to navigate to another screen navigate("ThirdScreen");
Regarding the second approach, if your component is a modal, you can pass the navigate object as - <Modal navigation={navigate} /> and in the modal component you can use it as this.props.navigation("ThirdScreen");
Hope it clarifies now.
Support we have js named SecondScreen.js at the same directory level as App.js then we should import it like this in App.js
import SecondScreen from './SecondScreen';
It worked for me. Hope this helps to you too.
I think you are trying to implement the functionality of a stack navigator.
Go to React-Navigation-Docs. In stack navigator you can make stack of screens, and navigate from one to another. Inside index.js :
import { StackNavigator, TabNavigator } from "react-navigation";
import SplashScreen from "./src/screens/start/splash";
import LoginScreen from "./src/screens/start/login";
import DomainScreen from "./src/screens/start/domain";
const App = StackNavigator(
{
Splash: {
screen: SplashScreen,
},
Domain: {
screen: DomainScreen,
},
Login: {
screen: LoginScreen,
},
Tabs: {
screen: HomeTabs,
}
},
{
initialRouteName: "Splash",
}
);
AppRegistry.registerComponent("app_name", () => App);
then you can navigate to any of these screens using this.props.navigation.navigate("ScreenName")