Render both Stack and Tab Navigator - react-native

I'm pretty new at react-native, please bear with me. I have a Stack and Tab navigator that both work well but independently. I, however, need them to work together.
const MainTabs = TabNavigator({
Messages: { screen: MessageScreen },
Cards: { screen: CardScreen },
Statements: { screen: StatementScreen },
Profile: { screen: ProfileScreen },
},
{
tabBarOptions: {
activeTintColor: bongzBlue,
inactiveTintColor: 'gray',
},
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false,
}
);
export default class App extends Component {
render() {
return (
// <RootStack />
<MainTabs />
);
}
}

Here is a suggestion:
You can nest the StackNavigator in a TabNavigator. So for your specific case, you can make your screens StackNavigators.
For example, your Messages screen can be created like this:
const MessagesStack = StackNavigator({
index: { screen: MessageScreen }
...
})
and then you can use it in your TabNavigator and export that as your main component.
const MainTabs = TabNavigator({
Messages: { screen: MessageStack },
...
},
Hope this helps.

Related

Screen navigate from stacknavigator is not working when using bottomtabnavigator

I'm new to react native, and I've problem with navigating between one of my screen to another.
I'm using stacknavigator like this:
const RootStack = createStackNavigator(
{
Splash: { screen: SplashScreen},
Mobile:{screen:MobileAuthentication} ,
Code:{screen:CodeAuthentication} ,
Home: { screen: HomeScreen },
ProfileScreen: { screen: ProfileScreen },
ProfileDetails: { screen: ProfileDetails },
},
{ initialRouteName: 'Splash'}
);
const AppContainer = createAppContainer(RootStack);
In my homeScreen I am using buttomtabnavigator
const bottomTabNavigator = createBottomTabNavigator(
{
A: {
screen: ProfileScreen,
navigationOptions: {
...
}
},
B: {
screen: FilterScreen,
navigationOptions: {
...
}
},
},
{
initialRouteName: 'FilterScreen',
tabBarOptions: {
activeTintColor: '#3F51B5'
}
}
);
const AppContainer = createAppContainer(bottomTabNavigator);
The problem is that when I want to navigate from ProfileScreen to ProfileDetails by onpress then it's not working
<ProfileBtn
onPress={() => {
console.log('item Clicked'),
this.props.navigation.navigate('ProfileDetails')
} }
/>
Maybe you should try to pass "navigation" into your stackNavigator creation, using the options with smthg like this (for each of your stack screen or at least those within which you want to use it) :
options={({route, navigation}) => (
{headerTitle: 'Splash',
route: {route},
navigation: {navigation}}
)}
If that's not the answer, please provide us with the error you get in your console.

Custom header in nested TabNavigator

I have a fairly complication navigation flow requirement for an app I'm working on.
I have a bottom tab bar, for each tab I'll be having a top tab bar for additional related views.
Which I have working, however on the videos tab in the nested "All" tab, I need to add a search bar to the header, and on the "Favourites" tab I'll be having yet another custom header with an "Edit" button at the top right.
How can I achieve this navigation whilst allowing React Navigation to co-ordinate everything. See images below:
What I don't want to do is disable the header at the MainNavigator level and enable it for particular routes. Or even worse embed the header and the tab bar on individual containers.
routes.js
import {
StackNavigator,
TabNavigator,
DrawerNavigator
} from "react-navigation";
import Feed from "./containers/Feed";
import Auth from "./containers/Auth";
import News from "./containers/News";
import Videos from "./containers/Videos";
import FavouriteVideos from "./containers/FavouriteVideos";
const DashboardNavigator = TabNavigator(
{
Feed: {
screen: Feed
},
News: {
screen: News
}
},
{
tabBarPosition: "top"
}
);
const VideoNavigator = TabNavigator(
{
Videos: {
screen: Videos,
navigationOptions: {
title: "All"
}
},
Favourites: {
screen: FavouriteVideos
}
},
{
tabBarPosition: "top"
}
);
const MainNavigator = TabNavigator(
{
Dashboard: {
screen: DashboardNavigator,
navigationOptions: ({}) => ({
title: "Dashboard"
})
},
Video: {
screen: VideoNavigator,
navigationOptions: ({}) => ({
title: "Videos"
})
}
},
{
swipeEnabled: false,
animationEnabled: false,
tabBarPosition: "bottom"
}
);
const AuthenticatedNavigator = DrawerNavigator({
App: {
screen: MainNavigator
}
});
const RootNavigator = StackNavigator({
LoggedOut: {
screen: Auth
},
Authenticated: {
screen: AuthenticatedNavigator
}
});
export default RootNavigator;
Snack
https://snack.expo.io/H1qeJrLiM
Images
You can use react-navigation addListener function with combination setParams to achieve desired behavior.
You can listen for focus and blur events and then change a parameter. Then in your route config you can look for this parameter and decide what to render for header. I changed your snack to show a working example of what I am suggesting.
Example
const MainNavigator = TabNavigator(
{
Dashboard: {
screen: DashboardNavigator,
navigationOptions: ({}) => ({
title: "Dashboard"
})
},
Video: {
screen: VideoNavigator,
navigationOptions: ({navigation}) => {
let title = 'Videos';
navigation.state.routes.forEach((route) => {
if(route.routeName === 'Videos' && route.params) {
title = route.params.title;
}
});
// I set title here but you can set a custom Header component
return {
tabBarLabel: 'Video',
title
}
}
}
},
{
swipeEnabled: false,
animationEnabled: false,
tabBarPosition: "bottom"
}
);
export default class Videos extends Component {
constructor(props) {
super(props);
this.willFocusSubscription = props.navigation.addListener(
'willFocus',
payload => {
this.props.navigation.setParams({title: 'All Videos'});
}
);
this.willBlurSubscription = props.navigation.addListener(
'willBlur',
payload => {
this.props.navigation.setParams({title: 'Just Videos'});
}
);
}
componentWillUnmount() {
this.willFocusSubscription.remove();
this.willBlurSubscription.remove();
}
render() {
return (
<View>
<Text> Videos </Text>
</View>
);
}
}

Not able to get DrawerNavigator to work in React Navigation

my code from that entire page is included below and my entire repo is here:
https://github.com/practicia1234/Practicia/commit/d66a23beece1b293c51b4b791f546a2351e6351b
. I am somehow not able to get this drawer navigation to work. For my model, I used the tutorial from here. This is the repo for that tutorial since it has a similar set up as mine, meaning that the first few screens are sign up and login screens and do not have a drawer exposed to the user. I am not sure what i am doing wrong here and would really appreciate if someone could help me a little. Trying to understand drawer navigation for the first time. Thanks!
Here is the error i get:
import React from 'react';
import { Text, Animated, Easing } from 'react-native';
import { StackNavigator, TabNavigator, DrawerNavigator } from 'react-navigation';
// Home scenes
import Home from '../scenes/Home';
import Dashboard from '../scenes/Dashboard';
// Authentication scenes
import Login from '../scenes/authentication/Login';
import SignUpStep from '../scenes/authentication/SignUpStep';
import SelectTeachers from '../scenes/authentication/SelectTeachers';
// import Dashboard from '../components/Dashboard'
// import FeedScreen from '../components/FeedScreen'
import AwardsScreen from '../scenes/award/AwardsScreen';
// import StudentsScreen from '../components/StudentsScreen'
import GameOnScreen from '../scenes/game/GameOnScreen';
// All practice scenes
import AllPractice from '../scenes/practice/AllPractice';
import Practice from '../scenes/practice/Practice';
import PlayingTests from '../scenes/practice/PlayingTests';
import Questions from '../scenes/practice/Questions';
import Individuals from '../scenes/students/individuals';
import FirstScreen from '../scenes/drawer/FirstScreen';
import SecondScreen from '../scenes/drawer/SecondScreen';
import ThirdScreen from '../scenes/drawer/ThirdScreen';
// Group
import Groups from '../scenes/students/groups';
// Upload
import UploadsScreen from '../scenes/upload/UploadsScreen';
import Pending from '../scenes/students/pending';
//import DrawerContainer from '.../components/DrawerContainer'
// const noTransitionConfig = () => ({
// transitionSpec: {
// duration: 0,
// timing: Animated.timing,
// easing: Easing.step0
// }
// });
// Constant for tab menus
const submissionMenu = {
screen: TabNavigator({
All: { screen: AllPractice },
Practice: { screen: Practice },
PlayingTests: { screen: PlayingTests },
Questions: { screen: Questions }
}, {
tabBarPosition: 'top',
flex: 2 / 3,
tabBarOptions: {
activeTintColor: '#33ACDE',
labelStyle: {
fontSize: 12,
},
tabStyle: {
width: 50,
},
}
}
)
};
const studentMenu = {
screen: TabNavigator({
Individuals: { screen: Individuals },
Groups: { screen: Groups },
Pending: { screen: Pending }
}, {
tabBarPosition: 'top',
flex: 2 / 3,
tabBarOptions: {
activeTintColor: '#33ACDE',
labelStyle: {
fontSize: 12,
},
tabStyle: {
width: 50,
},
}
}
)
};
const DrawerStack = DrawerNavigator({
screen1: { screen: FirstScreen },
screen2: { screen: SecondScreen },
screen3: { screen: ThirdScreen },
});
const DrawerNavigation = StackNavigator({
DrawerStack: { screen: DrawerStack }
}, {
headerMode: 'float',
navigationOptions: ({ navigation }) => ({
headerStyle: { backgroundColor: '#4C3E54' },
title: 'Welcome!',
headerTintColor: 'white',
})
});
const LoginStack = StackNavigator({
home: { screen: Home },
signup: { screen: SignUpStep },
login: { screen: Login },
selectTeachers: { screen: SelectTeachers },
dashboard: {
screen: TabNavigator({
Submissions: submissionMenu,
Students: studentMenu,
Awards: { screen: AwardsScreen },
GameOn: { screen: GameOnScreen },
Uploads: { screen: UploadsScreen }
}, {
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: '#33ACDE',
labelStyle: {
fontSize: 12,
},
tabStyle: {
width: 50,
}
}
}),
},
},
{
headerMode: 'float',
navigationOptions: {
headerStyle: { backgroundColor: '#E73536' },
title: 'You are not logged in',
headerTintColor: 'white'
}
});
const navigator = StackNavigator({
loginStack: { screen: LoginStack },
drawerStack: { screen: DrawerNavigation }
}, {
// Default config for all screens
headerMode: 'none',
title: 'Main',
initialRouteName: 'loginStack'
});
export default navigator;
When you execute navigation.navigate('DrawerOpen').
That 'navigation' is not drawer's but StackNavigation's.
If you want to access drawer's navigation, you should call it from children screen in Drawer like FirstScreen, SecondScreen or ThirdScreen.
Execute this.props.navigation.navigate('DrawerOpen') from those Screen.

not sure how to implement a drawer navigator in my project

I am trying to implement a drawer navigator in my project. The drawer will appear in all of the following Scenes: AllPractice, Practice, Playing Tests, Question (all tabs)
Individuals, Groups, Pending. (also tabs).
And all of the other main screens: Awards, GameOn, Uploads.
The issue is I don't know where to implement it in my project.
All my navigation is in the navigation folder.
This is the basic code for the drawer:
AppDrawerNavigator = DrawerNavigator({
FirstScreen: { Screen: FirstScreen },
SecondScreen: { Screen: SecondScreen }
});
Here is where all my navigation code is: its in this file
import { StackNavigator, TabNavigator, DrawerNavigator } from 'react-navigation';
// Home scenes
import Home from '../scenes/Home';
// Authentication scenes
import Login from '../scenes/authentication/Login';
import SignUpStep from '../scenes/authentication/SignUpStep';
import SelectTeachers from '../scenes/authentication/SelectTeachers';
// import Dashboard from '../components/Dashboard'
// import FeedScreen from '../components/FeedScreen'
import AwardsScreen from '../scenes/award/AwardsScreen';
// import StudentsScreen from '../components/StudentsScreen'
import GameOnScreen from '../scenes/game/GameOnScreen';
// All practice scenes
import AllPractice from '../scenes/practice/AllPractice';
import Practice from '../scenes/practice/Practice';
import PlayingTests from '../scenes/practice/PlayingTests';
import Questions from '../scenes/practice/Questions';
import Individuals from '../scenes/practice/Individuals';
import FirstScreen from '../scenes/drawer/firstScreen';
import SecondScreen from '../scenes/drawer/secondScreen';
// Group
import Groups from '../scenes/group/Groups';
// Upload
import UploadsScreen from '../scenes/upload/UploadsScreen';
import Pending from '../scenes/upload/Pending';
// Constant for tab menus
const submissionMenu = {
screen: TabNavigator({
All: { screen: AllPractice },
Practice: { screen: Practice },
PlayingTests: { screen: PlayingTests },
Questions: { screen: Questions }
}, {
tabBarPosition: 'top',
flex: 2 / 3,
tabBarOptions: {
activeTintColor: '#33ACDE',
labelStyle: {
fontSize: 12,
},
tabStyle: {
width: 50
},
}
}
)
};
const studentMenu = {
screen: TabNavigator({
Individuals: { screen: Individuals },
Groups: { screen: Groups },
Pending: { screen: Pending }
}, {
tabBarPosition: 'top',
flex: 1 / 2,
tabBarOptions: {
activeTintColor: '#33ACDE',
}
}
)
};
// Navigation defined
const navigator = StackNavigator({
home: { screen: Home },
signup: { screen: SignUpStep },
login: { screen: Login },
selectTeachers: { screen: SelectTeachers },
dashboard: {
screen: TabNavigator({
Submissions: submissionMenu,
Students: studentMenu,
Awards: { screen: AwardsScreen },
GameOn: { screen: GameOnScreen },
Uploads: { screen: UploadsScreen }
}, {
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: '#33ACDE',
}
}),
navigationOptions: {
title: 'PRACTICIA',
headerLeft: null,
headerStyle: {
backgroundColor: '#33ACDE',
},
headerTitleStyle: {
color: 'white'
}
}
}
});
export default navigator;
Drawer Navigation is like a Tab navigation. It means if you want to use a Drawer to offer a user to navigate your app, then forget about the tabs.
Or, if you want to use a drawer just as a controller like you put some buttons on it.
then, it will be like this.
AppDrawerNavigator = DrawerNavigator({
FirstScreen: { Screen: navigator },
});
I put your 'navigator' on the drawer navigation. Then you can use AppDrawerNavigator as a root.
Then, you can use 'contentComponent' in drawerNavigatorOption to put some buttons or view.

Adding tab component in a view

I am new to react native, and I am struggling to understand it. This may be a very basic question.
I have a screen and it consists of a searchbar on top of the page and below it there are Tabs. While navigating through the tabs, the searchbar should not be removed (being at the top level).
MainScreen:
export default class MainScreen extends Component {
render() {
return (
<View>
<Text>My search bar here</Text>
<TabBar></TabBar>
</View>
);
}
}
TabBar:
const routeConfiguration = {
TabEvents: { screen: TabEvents },
TabPeople: { screen: TabPeople },
TabGroups: { screen: TabGroups },
TabMap: { screen: TabMap },
}
const tabBarConfiguration = {
tabBarOptions:{
// some options
}
}
export const TabBar = TabNavigator(routeConfiguration,tabBarConfiguration)
When running the app, only the text is being displayed My search bar here without the tabs.
To be able to show tabs, the navigator acts like a container with "two views". One is for the screens that you wanna show and, at the bottom, the tabs container.
So, for the MainScreen you just only need to define the tabs/screens that want react navigator to render.
In each screen you will put the header as shown above. You could also define a default header in the navigator props.
MainScreen.js:
const MainScreen = TabNavigator({
TabEvents: { screen: TabEvents },
Second: { screen: SecondPage },
Third: { screen: ThirdPage },
Fourth: { screen: FourthPage },
Fifth: { screen: FifthPage }
}
})
export default MainScreen;
MainScreen.js: (with default header)
const MainScreen = TabNavigator({
TabEvents: { screen: TabEvents },
Second: { screen: SecondPage },
Third: { screen: ThirdPage },
Fourth: { screen: FourthPage },
Fifth: { screen: FifthPage }
}, {
navigationOptions: {
header: <YourHeader />
}
})
export default MainScreen;
TabEvents.js
export default class TabEvents extends Component {
render() {
return (
<View>
<YourHeader />
<MoreStuff/>
</View>
);
}
}
You wil have a more detailed example in the docs ( https://github.com/react-community/react-navigation/blob/master/examples/NavigationPlayground/js/SimpleTabs.js & https://reactnavigation.org/docs/navigators/tab)
You can wrap your TabNavigator with StackNavigator.
MyTabNavigator.js
const MyTabNavigator = TabNavigator({
ScreenX: { screen: SceenNameX },
ScreenY: { screen: ScreenNameY }
}, {
initialRouteName: 'ScreenX',
tabBarPosition: 'top',
tabBarOptions: {
activeTintColor: '#af0'
}
})
export default MyTabNavigator
MainScreen.js
export default class MainScreen extends Component {
static navigationOptions = {
header: (props) => (
<SearchBar {...props}/>
)
}
render() {
return (
<MyTabNavigator />
)
}
}
MyStackNavigator.js
const MyStackNavigator = StackNavigator({
Main: { screen: MainScreen }
}, {
initialRouteName: 'Main'
})
export default MyStackNavigator
Now you can call MyStackNavigator to load MainScreen which will render the header SearchBar and the body MyTabNavigator.
The way to create a Tab navigator is the following:
tabNavigator.js
import React from 'react'
import { Platform } from 'react-native'
import { TabNavigator, StackNavigator } from 'react-navigation'
const Tabs = TabNavigator({
Home:{ //this is the name of the screen, by default the first screen that you want to show is called Home
screen: component , //this is the component that you want to show in the screen
navigationOptions: {
tabBarLabel: 'some label', //this will be located as a title for the tab
tabBarIcon: ({ tintColor }) => <i> some icon </i>, //this allow you to show a icon in the tab
//the following options are to customize the header, maybe you don't need this.
title: 'some title',
headerStyle:{
backgroundColor: 'blue' // color for the header
},
headerTitleStyle:{
color: 'white' // color for the text on the header
},
header: <YourHeader/>
}
},
// if you need add some other tab repeat the same pattern here OtherScreen:{ ...}
},{
//this are options to customize the tab itself, I added some good ones.
tabBarOptions: {
activeTintColor: Platform.OS === 'ios' ? primary : white,
style:{
height:40,
backgroundColor: Platform.OS === 'ios' ? white : primary,
shadowRadius: 6,
shadowOpacity: 1,
shadowColor: 'rgba(0,0,0,0.24)',
shadowOffset: {
width: 0,
height: 3
}
}
}
})
export default Tabs
mainScreen.js
import React, { Component} from 'react'
import Tabs from './tabNavigator'
export default class MainScreen extends Component {
render() {
return (
<View>
<Tabs/>
</View>
);
}
}
I hope it helps.