I am working with an Expo app which comes bundles with the react-native-navigation.
It works great and I have setup several Stacked Navigations but I cannot seem to get my modals to display without the bottom Tab Navigator.
Below is the navigation folder structure:
Here are the files:
AppNavigator.js
import { createSwitchNavigator } from 'react-navigation'
import MainTabNavigator from './MainTabNavigator'
export default createSwitchNavigator({
Main: MainTabNavigator
})
MainTabNavigator.js
import React from 'react'
import { Platform } from 'react-native'
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation'
// Import Stacks
import SettingsStack from './stacks/SettingsStack.js'
// Import Components
import TabBarIcon from '../components/TabBarIcon'
// Import Screens
import HomeScreen from '../screens/HomeScreen'
import ExercisesScreen from '../screens/ExercisesScreen'
import ExerciseDetailScreen from '../screens/ExerciseDetailScreen'
import VideoScreen from '../screens/VideoScreen'
import ExerciseStartScreen from '../screens/ExerciseStartScreen'
const HomeStack = createStackNavigator({
Home: HomeScreen,
ExerciseDetails: ExerciseDetailScreen
})
const StartWorkOut = createStackNavigator({
Home: HomeScreen,
ExerciseStart: ExerciseStartScreen
})
StartWorkOut.navigationOptions = {
tabBarVisible: false
}
const RootStack = createStackNavigator({
Main: HomeStack,
ExerciseStart: ExerciseStartScreen,
VideoScreen: {
screen: VideoScreen
}
},
{
mode: 'modal',
headerMode: 'none',
tabBarVisible: false
})
const ExercisesStack = createStackNavigator({
Exercises: ExercisesScreen,
ExerciseDetails: ExerciseDetailScreen
})
const ExerciseRootStack = createStackNavigator({
Main: ExercisesStack,
VideoScreen: {
screen: VideoScreen
}
},
{
mode: 'modal',
headerMode: 'none',
tabBarVisible: false
})
RootStack.navigationOptions = {
tabBarLabel: 'Home',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-information-circle${focused ? '' : '-outline'}`
: 'md-information-circle'
}
/>
)
}
ExerciseRootStack.navigationOptions = {
tabBarLabel: 'Exercises',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-information-circle${focused ? '' : '-outline'}`
: 'md-information-circle'
}
/>
)
}
export default createBottomTabNavigator({
RootStack,
ExerciseRootStack,
SettingsStack
})
The settings Stack file is not important and I have tried adding the following into screens, without any luck:
static navigationOptions = {
tabBarVisible: false
}
Thanks!
I managed to figure it out in the end.
I had to refactor the code and remove the modals from the tab navigator and add it directly to the AppNAvigator.js as below:
import { createStackNavigator } from 'react-navigation'
import MainTabNavigator from './MainTabNavigator'
// Import Screens
import HomeScreen from '../screens/HomeScreen.js'
import ExerciseStartScreen from '../screens/ExerciseStartScreen.js'
import VideoScreen from '../screens/VideoScreen.js'
export default createStackNavigator({
Main: MainTabNavigator,
ExerciseStart: ExerciseStartScreen,
VideoScreen: VideoScreen
},
{
mode: 'modal',
headerMode: 'none',
navigationOptions: {
header: null
}
})
Related
I've tried to open the drawer by clicking the following button (screenshot) in a specific scene.
current status
and here goes my code.
// App.js
import React, { Component } from 'react';
import { createAppContainer, createSwitchNavigator } from 'react-navigation'
import { createStackNavigator } from 'react-navigation-stack'
import { createDrawerNavigator } from 'react-navigation-drawer'
import SplashScreen from 'react-native-splash-screen'
import RNBootSplash from "react-native-bootsplash"
import MainCategory from './src/Scenes/MainCategory'
import SubCategory from './src/Scenes/SubCategory'
import DetailScene from './src/Scenes/DetailScene'
import Questions from './src/Scenes/Questions'
import Ruleta from './src/Scenes/Ruleta'
import CustomDrawerComponent from './src/Components/CustomDrawerComponent'
export default class MainRouter extends Component {
componentDidMount() {
SplashScreen.hide()
RNBootSplash.hide({ duration: 250 })
}
render() {
const StackNavigator = createStackNavigator({
MainCategory: {screen: MainCategory},
SubCategory: {screen: SubCategory},
DetailScene: {screen: DetailScene},
Questions: {screen: Questions},
Ruleta: {screen: Ruleta},
}, {
initialRouteName: "MainCategory",
headerMode: "none"
})
const DrawerNavigator = createDrawerNavigator({
MainCategory: {screen: MainCategory},
}, {
drawerPosition: 'right',
contentComponent: CustomDrawerComponent
})
const MainNavigator = createSwitchNavigator({
Stack: StackNavigator,
Drawer: DrawerNavigator,
}, {
initialRouteName: 'Stack',
contentComponent: CustomDrawerComponent
})
const AppContainer = createAppContainer(MainNavigator)
return(
<AppContainer />
)
}
}
// Specific scene
import React, { Component } from 'react'
import { ScrollView, StatusBar, View, TouchableOpacity, Text, Image, Modal } from 'react-native'
import HeaderBar from '../Components/HeaderBar'
export default class Questions extends Component {
constructor(props) {
super(props)
this.state = {
headerTitle: props.navigation.getParam('headerTitle'),
catId: props.navigation.getParam('catId'),
}
}
openSideMenu = () => {
this.props.navigation.toggleDrawer
this.props.navigation.openDrawer()
}
render() {
return (
<View style={rootStyle}>
<View>
<StatusBar hidden={false} translucent backgroundColor="transparent" barStyle="light-content" />
<HeaderBar title={headerTitle} onPressLeft={() => this.props.navigation.goBack()} leftShow={true} onPressRight={this.openSideMenu} rightShow={true} />
</View>
<ScrollView>
<QuestionList todoQues={todoQues} favQues={favQues} action={this.action.bind(this)} />
</ScrollView>
</View>
)
}
}
But it's not working.
I expect the result like the following screenshot.
expected result
Please let me know what I should do more and how to use the drawer navigator in a specific scene.
Thanks for your time!
First of all instead of calling the method this.props.navigation.toggleDrawer(), call the method this.props.navigation.dispatch(DrawerActions.openDrawer()).
You also need to import DrawerActions for this to work. And remove the first function that you called in your openSideMenu function because you don't need the this.props.navigation.openDrawer()
In my app, I have buttons navigate to other screens and I have a drawer have buttons as well,
I did the drawer and it works fine and also did stack navigation and also works fine, but in my app.js when I define one of them (drawer or stack) the other not working, I will provide my code, I think the problem is that I declared createAppContainer for both of them separately, How I do combine between them?
Here is my code:
Root.js:
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import Main from "./Main.js";
import Signup from "./Signup.js";
import Home from "./Home.js";
import CardDetails from "./CardDetails";
import Profile from "./Profile";
const MainNavigator = createStackNavigator(
{
Main: { screen: Main },
Profile: { screen: Profile },
Signup: { screen: Signup },
Home: { screen: Home },
CardDetails: { screen: CardDetails },
},
{
initialRouteName: "Main",
navigationOptions: {
header: null
},
initialRouteParams: {
navigationMode: true
}
}
);
const Root = createAppContainer(MainNavigator);
export default Root;
DrawerNavigator.js:
import React from "react";
import { Platform, Dimensions } from "react-native";
import { createAppContainer } from "react-navigation";
import { createDrawerNavigator } from "react-navigation-drawer";
import MyProduct from "../Containers/MyProduct";
import Home from "../Containers/Home";
import Profile from "../Containers/Profile";
import Main from "../Containers/Main";
import Signup from "../Containers/Signup.js";
import MenuDrawer from "../Components/MenuDrawer";
const { width, height } = Dimensions.get("window");
const DrawerConfig = {
drawerWidth: width * 0.83,
contentComponent: ({ navigation }) => {
return <MenuDrawer navigation={navigation} />;
}
};
export const DrawerNavigator = createDrawerNavigator(
{
MyProduct: {
screen: MyProduct
},
Profile: {
screen: Profile
},
Main: {
screen: Main
},
Home: {
screen: Home
},
},
{initialRouteName:'Main'},
DrawerConfig
);
export default createAppContainer(DrawerNavigator);
App.js:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow
*/
import React from "react";
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
StatusBar
} from "react-native";
// import { Provider } from 'react-redux';
import {
Header,
LearnMoreLinks,
Colors,
DebugInstructions,
ReloadInstructions
} from "react-native/Libraries/NewAppScreen";
import Main from './src/Containers/Main.js'
import Login from './src/Containers/Login.js'
import Signup from './src/Containers/Signup.js'
import Home from './src/Containers/Home.js'
import CardDetails from './src/Containers/CardDetails'
import AddMobile from './src/Containers/AddMobile'
import Profile from './src/Containers/Profile'
import MyProduct from './src/Containers/MyProduct'
import Root from './src/Containers/Root'
import DrawerNavigator from './src/Navigation/DrawerNavigator';
import Navigators from './src/Navigation/Navigators';
import MenuButton from "./src/Components/MenuButton.js";
const App: () => React$Node = () => {
return (
// <DrawerNavigator /> /// here the drawer works fine but stack navgation not working
<Root /> ////here stacknavigations work fine but I got an error when I press drawer icon. Error screenshot pasted in the end.
);
};
const styles = StyleSheet.create({
});
export default App;
You can try it in this way.
const DrawerNavigators = createDrawerNavigator({
//Drawer Optons and indexing
Main: {
screen: HomeActivity_StackNavigator,
navigationOptions: {
drawerLabel: 'Dashboard',
}
}
});
const NonDrawerNavigators = createStackNavigator({
TaskView: {
screen: TaskView,
navigationOptions: {
title: 'Task',
headerStyle: {
backgroundColor: '#FF9800',
},
headerTintColor: '#fff'
}
},
TeamView: {
screen: TeamView,
navigationOptions: {
title: 'Team',
headerStyle: {
backgroundColor: '#FF9800',
},
headerTintColor: '#fff'
}
}
}, {headerLayoutPreset: 'center'});
const AppNavigator = createStackNavigator({
drawerStack: {
screen: DrawerNavigators,
navigationOptions: {
header: null
}
},
nonDrawerStack: {
screen: NonDrawerNavigators,
navigationOptions: {
header: null
}
}
});
export default createAppContainer(createSwitchNavigator({
SplashScreen: SplashScreen,
loginStack: LoginNavigator,
homeStack: AppNavigator
}, {
initialRouteName: 'SplashScreen'
})
);
Hi Have a react navigation method which make a drawer, which is inside a createSwitchNavigator. But when doing the final call I am not able to render the drawer correctly. I am getting
Invariant violation error coming.
This is my drawer:
const MyDrawerNavigator = createDrawerNavigator({
Home:{
screen: DashboardScreen,
},
Notifications: {
screen: UserMeetingScreen,
},
});
const MyApp = createAppContainer(MyDrawerNavigator);
export default MyApp
This is my stacknavigator
import AppStack from '../navigator/loggedIn';
import AuthStack from '../navigator/loggedOut';
import LoadingScreen from '../components/Loading/loading.component';
export const GetAppStack = createAppContainer(createSwitchNavigator(
{
AuthLoading: LoadingScreen,
LoggedOut: AuthStack,
LoggedIn: AppStack,
},
{
initialRouteName: 'AuthLoading',
}
))
And this is my dashboard component
export default class DashboardScreen extends React.Component{
static navigationOptions = {
headerMode: 'none',
headerStyle:{
backgroundColor: '#4F6D7A',
elevation: 0
}
}
render(){
return (
<View>
<OfflineNotice />
<Icon
name= 'flight-takeoff'
onPress= {()=> this.props.navigation.openDrawer()}
></Icon>
</View>
)
}
}
I am getting a Element type is invalid error. Check render method of Dashboard screen. What am I doing wrong?
I have this in my react-native code:
const MainNavigator = createBottomTabNavigator({
Home: Home,
"Exercise List": ExerciseList,
Exercise: Exercise,
"Current Workout": CurrentWorkout,
})
but I only want to navigate to the Exercise tab when I click to it via the exerciseList page like so:
onPress={() => navigate("Exercise", { name: item.name })}
and I don't want it to appear in the navigation bar at the bottom. But if I remove it from MainNavigator above then it doesn't work when I click the onPress above. Is there a way to Navigate to the component without it being in the tab nav?
You need to make some change in app.js. add createBottomTabNavigator inside createStackNavigator. Add those component into stacknavigator in which you do not want to add into bottom tab navigator. In createBottomTabNavigator add those component which you want to show in tab bar
Please check following code
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View,
SafeAreaView,
ScrollView,
Dimensions
} from "react-native";
import { createStackNavigator, createBottomTabNavigator } from "react-navigation";
import LoginScreen from "./Screens/LoginScreen";
export default class App extends Component {
render() {
return <StackNav />;
}
}
const StackNav = createStackNavigator(
{
TabNavigator: {
screen: AppTabNavigator,
navigationOptions: {
headerMode: "none",
header: null
}
},
First: {
screen: First,
navigationOptions: {
headerMode: "none",
header: null
}
},
Second: {
screen: Second,
navigationOptions: {
headerMode: "none",
header: null
}
}
},
{
initialRouteName: "TabNavigator"
}
);
const AppTabNavigator = createBottomTabNavigator({
Login: {
screen: LoginScreen
}
});
Add it with createSwitchNavigator. A working example is given below
const Navigation = createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppStack,
Auth: AuthStack,
Qr: QrPage,
},
{
initialRouteName: 'AuthLoading',
}
Here I can access to my Qr page from any where.
here is two method of of call other components which doesn't contains in tabNavigator:
const otherAppNavigator = createStackNavigator({//all of this are not in TabNavigator
dashboard: {
screen: Dashboard,
},
userProfile: {
screen: UserProfile
},
onGoingPickup: {
screen: OnGoingPickup
},
});
const TabNavigator = createBottomTabNavigator({
home: otherAppNavigator,//<<<<<<<<<<
about:foo,
}
)
const MainNavigator = createSwitchNavigator({
firstPage: {//it's not in TabNavigator<<<<<<<<<<<<<<<<<<<<<<<<<<
screen: Login,
},
verification: {//its not in TabNavigator<<<<<<<<<<<<<<<<<<<<<<<<
screen: verification
},
dashboard: {
screen: TabNavigator
}
})
export default createAppContainer(MainNavigator); //the main navigator is which you bind in here
pay attention to the last line ....!!!!
hope to be helpful.
I have three .js files in my react native project:
App.js
LoginPage.js
RootNavigation.js
My launcher screen is LoginPage.js now i need to go to Rootnavigation.js .
RootNavigation.js has import MainTabnavigator.js
App.js:
import React from 'react';
import { Platform, StatusBar, StyleSheet, View } from 'react-native';
import { AppLoading, Asset, Font } from 'expo';
import { Ionicons } from '#expo/vector-icons';
import RootNavigation from './navigation/RootNavigation';
import LoginPage from './screens/LoginPage';
import { createSwitchNavigator, createStackNavigator } from 'react-navigation';
export class App extends React.Component {
state = {
isLoadingComplete: false,
};
render() {
if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
);
} else {
return (
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<RootNavigation />
</View>
);
}
}
_loadResourcesAsync = async () => {
return Promise.all([
Asset.loadAsync([
require('./assets/images/robot-dev.png'),
require('./assets/images/robot-prod.png'),
]),
Font.loadAsync({
// This is the font that we are using for our tab bar
...Ionicons.font,
// We include SpaceMono because we use it in HomeScreen.js. Feel free
// to remove this if you are not using it in your app
'space-mono': require('./assets/fonts/SpaceMono-Regular.ttf'),
}),
]);
};
_handleLoadingError = error => {
// In this case, you might want to report the error to your error
// reporting service, for example Sentry
console.warn(error);
};
_handleFinishLoading = () => {
this.setState({ isLoadingComplete: true });
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
export default justsms = createStackNavigator(
{
First: { screen: LoginPage },
Second: { screen: App }
});
LoginPage.js:
import React from 'react';
import {Image, Platform, ScrollView, StyleSheet, Text, TouchableOpacity, View, Button} from 'react-native';
export default class LoginPage extends React.Component {
static navigationOptions={
title:'Login Page'
};
NavigateActivityFunction = () =>
{
this.props.navigation.navigate('Second');
}
render(){
return(<View style={styles.container}>
<Button title='Tab Activity' onPress={this.NavigateActivityFunction}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent:'center'
}
});
RootNavigation.js:
import React from 'react';
import { Notifications } from 'expo';
import { createSwitchNavigator } from 'react-navigation';
import MainTabNavigator from './MainTabNavigator';
import registerForPushNotificationsAsync from '../api/registerForPushNotificationsAsync';
const AppNavigator = createSwitchNavigator({
// You could add another route here for authentication.
// Read more at https://reactnavigation.org/docs/en/auth-flow.html
Main: MainTabNavigator,
});
export default class RootNavigation extends React.Component {
componentDidMount() {
this._notificationSubscription = this._registerForPushNotifications();
}
componentWillUnmount() {
this._notificationSubscription && this._notificationSubscription.remove();
}
render() {
return <AppNavigator />;
}
_registerForPushNotifications() {
// Send our push token over to our backend so we can receive notifications
// You can comment the following line out if you want to stop receiving
// a notification every time you open the app. Check out the source
// for this function in api/registerForPushNotificationsAsync.js
registerForPushNotificationsAsync();
// Watch for incoming notifications
this._notificationSubscription = Notifications.addListener(this._handleNotification);
}
_handleNotification = ({ origin, data }) => {
console.log(`Push notification ${origin} with data: ${JSON.stringify(data)}`);
};
}
MainTabNavigator.js:
import React from 'react';
import { Platform } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation';
import TabBarIcon from '../components/TabBarIcon';
import HomeScreen from '../screens/HomeScreen';
import LinksScreen from '../screens/LinksScreen';
import SettingsScreen from '../screens/SettingsScreen';
const HomeStack = createStackNavigator({
Home: HomeScreen,
});
HomeStack.navigationOptions = {
tabBarLabel: 'Home',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-information-circle${focused ? '' : '-outline'}`
: 'md-information-circle'
}
/>
),
};
const LinksStack = createStackNavigator({
Links: LinksScreen,
});
LinksStack.navigationOptions = {
tabBarLabel: 'Links',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={Platform.OS === 'ios' ? `ios-link${focused ? '' : '-outline'}` : 'md-link'}
/>
),
};
const SettingsStack = createStackNavigator({
Settings: SettingsScreen,
});
SettingsStack.navigationOptions = {
tabBarLabel: 'Settings',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={Platform.OS === 'ios' ? `ios-options${focused ? '' : '-outline'}` : 'md-options'}
/>
),
};
export default createBottomTabNavigator({
HomeStack,
LinksStack,
SettingsStack,
});
Here when i click on button in LoginPage.js it should go to tab activity . I tried importing MainTabNavigator.js in App.js but when i click on button nothing is happening. I would be glad if someone Help me in this issue.