In my react native app, I have a stack navigator as so:
const AppStack = createStackNavigator(
{
Tabs: AppTabs,
Account: AccountScreen,
Profile: ProfileScreen,
Post: PostScreen,
},
);
The ProfileScreen contains some header content and another TabNavigator, in a layout similar to when you click on a channel in Youtube:
const ProfileTabs = createMaterialTopTabNavigator(
{
Home: ProfileHome,
Posts: ProfileMade,
},
);
const ProfileNav = createAppContainer(ProfileTabs);
class ProfileScreen extends React.Component {
render() {
return (
<View style={{ flex: 1 }}>
<View>Some header content</View>
<ProfileNav />
</View>
);
}
}
My problem is that I am unable to navigate from inside the ProfileTabs navigator to a screen in the original stacknavigator. E.g. if a user clicks on a post in the ProfileMade screen, I want to navigate them to the PostScreen.
Please can someone tell me what should be changed? Thanks
You can navigate to another stack sending the name of stack on the .navigate() method:
navigation.navigate('StackName', {
screen: 'YourScreenName'
});
Related
I am trying to use react native DrawerNavigator and StackNavigator together but for some reason I can't make it work.
Below is my code:
import {DrawerNavigator,StackNavigator, } from 'react-navigation'
class App extends Component {
render(){
return(
<View style={{flex:1,backgroundColor:'transparent'}}>
<AppStackNavigator/>
<AppDrawerNavigator/>
</View>
)
}
}
const AppDrawerNavigator = DrawerNavigator({
Home:HomeScreen,
Price:PriceScreen,
Info:InfoScreen,
Login:LoginScreen
})
const AppStackNavigator = StackNavigator({
Home:HomeScreen,
Price:PriceScreen,
Info:InfoScreen,
Login:LoginScreen
})
export default App
When I run this code my app screen is split into half, top have shows stackNavigator screen and the bottom half shows DrawerNavigator screen.
Is there a way I can make these two work together?
Also, what is the difference between stackNavigator and createStack Navigator? I don't see the diffence when I run these.
You need to nest the Navigators to get the result you are asking for.
For example if you want a stack navigation inside one of the screens in your drawer navigation you can do this:
import {DrawerNavigator, StackNavigator} from 'react-navigation'
class App extends Component {
render() {
return (
<View style={{ flex: 1, backgroundColor: 'transparent' }}>
<AppDrawerNavigator />
</View>
)
}
}
const AppStackNavigator = StackNavigator({
Home: HomeScreen,
Price: PriceScreen,
Info: InfoScreen,
Login: LoginScreen
})
const AppDrawerNavigator = DrawerNavigator({
Home: AppStackNavigator,
// Price: PriceScreen,
// Info: InfoScreen,
// Login: LoginScreen
})
export default App
The important part is
const AppDrawerNavigator = DrawerNavigator({
Home: AppStackNavigator, <--- This
// Price: PriceScreen,
// Info: InfoScreen,
// Login: LoginScreen
})
Now the "Home" Screen in your Drawer Navigation has the ability to use the stack navigation. You can do this for the others screens as well.
I am new to react native, and have come across this issue with navigation. I have a 'main menu' (TabNav) that I want to render on every page.
I have some pages that are not accessible from the main menu (TabNav), but should still have the menu options. I'm not sure how to impliment this. Here is the code I have so far:
const TabNav = createMaterialBottomTabNavigator({
Map: { screen: HomeScreen },
Details: { screen: Details },
});
const extraNav = createStackNavigator(
{
SinglePage: SinglePage,
Tabs: TabNav
}
);
const RootStackNav = createStackNavigator(
{
Tabs: {
screen: TabNav
},
SinglePage: {
screen: extraNav,
}
},
);
I navigate to the single separate page via:
render() {
const { navigation } = this.props;
return (
<View>
<Icon
name='place'
onPress={() => navigation.navigate('SinglePage')}
/>
</View>
);
}
What I want to happen is when I navigate to the single separate page my "main menu" is still present.
Right now I can navigate to all the pages, but on the single separate page the tabs are not available, and I have to hit 'back' to access it again.
You can use this code to nest a stack navigator to a tab navigator
const RootTabNav = createMaterialBottomTabNavigator({
Map: { screen: HomeScreen },
DetailStack: { screen: stackNav},
});
const stackNav= createStackNavigator(
{
SinglePage: { screen: SinglePage}
Details: { screen: Details },
}
);
Its just an example of nesting stack to tabNavigator. I hope this may help you.
I started learning React Native, I know how to create TabNavigator or DrawerNavigator but I need access to props.navigation on landing page where I don't have TabNavigation, how I'am supposed to get it.
I tried this:
const App = createStackNavigator({
LandingScreen: { screen: LandingScreen },
Register: { screen: RegisterScreen },
Login: { screen: LoginScreen}});
But still, this.props are empty object.
And what is stackNavigator in plain language, does it just define navigation in order to be able to use navigation ?
In your LandingScreen you can able to get the this.props.navigation. You can show your TabNavigation as your initial route. You can even set Stack Navigation for each Tab. For React Navigation(v2) Documentation https://reactnavigation.org/docs/en/tab-based-navigation.html
Stack Navigation:
Provides a way for your app to transition between screens where each new screen is placed on top of a stack.
//Stack Navigator
const App = createStackNavigator({
Home: { screen: Tabs }, //You can nest your TabNavigator here, Hence the LandingScreen inside your HomeStack will shown as your Initial screen
Register: { screen: RegisterScreen },
Login: { screen: LoginScreen}});
//Sample Tab Navigator
const Tabs = createBottomTabNavigator(
{
Home: HomeStack,
Settings: SettingsStack,
},
{
/* Other configuration remains unchanged */
}
);
const HomeStack = createStackNavigator({
LandingScreen: LandingScreen,
Details: DetailsScreen,
});
const SettingsStack = createStackNavigator({
Settings: SettingsScreen,
Details: DetailsScreen,
});
You can get your navigation Prop by using below
//LandingScreen Component
export default LandingScreen extends Component{
static navigationOptions = ({navigation}) => ({ //you can able to destructure your navigation prop here
headerTitle: 'Langing Page'
})
render(){
return(
//your logic here
)
}
}
I'm using React Navigation in my react native app, and I'm looking to render both the drawer navigation and tab navigation components simultaneously.
At first, I tried to render both in the root app component, but that threw an error that appears in their documentation here. I then attempted the solution listed below, which produced the following for me:
const TabNavigator = createBottomTabNavigator({
Settings: {
screen: SettingsScreen
}
});
const AppNavigator = createDrawerNavigator({
Home: {
screen: HomeScreen
},
Products: {
screen: ProductsScreen
},
TabNav: TabNavigator
});
export default class App extends React.Component {
render() {
return <AppNavigator />;
}
}
The tab navigation only shows when I select the TabNav link in the drawer navigation. I want it on every screen. I also don't want the TabNav label to show in the drawer navigation.
Am I missing something in the documentation, or is this the intended functionality?
For the first question, move the TabNav to first in the navigator like this
TabNav: TabNavigator,
Home: {
screen: HomeScreen
},
Products: {
screen: ProductsScreen
}
or else you change the initialRouteName to "TabNav"
For the Second question,
If you want the TabNavigation to show inside the HomeScreen and ProductsScreen you need to include TabNavigation in both
or they need to have a parent TabNavigation which contains those. I can add a sample code if you post what the TabNav contains.
And for the Third question,
You can use contentComponent in DrawerNavigator example like this
contentComponent: props => (
<AppDrawerContent {...props} navigation={props.navigation} />
),
Edited:
If you want TabNavigator to show on each one. I think you should change the way you Structure your navigator.
export default class App extends React.Component {
render() {
return < TabNavigator />;
}
}
const TabNavigator = createBottomTabNavigator({
Drawer: {
screen: AppNavigator
}
});
const AppNavigator = createDrawerNavigator({
Home: {
screen: HomeScreen
},
Products: {
screen: ProductsScreen
}
});
or else if you want TabNavigator inside each screen individually then
const AppNavigator = createDrawerNavigator({
HomeNavigator: {
screen: HomeScreenNavigator
},
Products: {
screen: ProductsScreen
}
});
const HomeScreenNavigator = createBottomTabNavigator({
Home: {
screen: HomeScreen
},
Settings: {
screen: SettingsScreen
}
});
export default class App extends React.Component {
render() {
return <AppNavigator />;
}
}
Like wise for Products screen also.
What you have actually done is you included the TabNav as Drawer Screen so it does appear in the Drawer side bar.
Even if this structure doesn't work you need to check on restructuring it. Or you may give a images how you want to show it. May be I could help you with better understanding.
I am using React Navigation's Tab Navigator from https://reactnavigation.org/docs/navigators/tab, when I switch between the Tab Screens I don't get any navigation state in this.props.navigation.
Tab Navigator:
import React, { Component } from 'react';
import { View, Text, Image} from 'react-native';
import DashboardTabScreen from 'FinanceBakerZ/src/components/dashboard/DashboardTabScreen';
import { TabNavigator } from 'react-navigation';
render() {
console.log(this.props.navigation);
return (
<View>
<DashboardTabNavigator />
</View>
);
}
const DashboardTabNavigator = TabNavigator({
TODAY: {
screen: DashboardTabScreen
},
THISWEEK: {
screen: DashboardTabScreen
}
});
DASHBOARD SCREEN:
import React, { Component } from 'react';
import { View, Text} from 'react-native';
export default class DashboardTabScreen extends Component {
constructor(props) {
super(props);
this.state = {};
console.log('props', props);
}
render() {
console.log('props', this.props);
return (
<View style={{flex: 1}}>
<Text>Checking!</Text>
</View>
);
}
}
I get props at Dashboard Screen when it renders the component first but I don't get props when I switch the tabs.
I need to get the current Screen name i.e TODAY or THISWEEK.
Your problem is about "Screen Tracking", react-navigation has an officially guide for this. you can use onNavigationStateChange to track the screen by using built-in navigation container or write a Redux middleware to track the screen if you want to integrate with Redux. More detail can be found at the officially guide: Screen-Tracking. Below is a sample code from the guide by using onNavigationStateChange:
import { GoogleAnalyticsTracker } from 'react-native-google-analytics-bridge';
const tracker = new GoogleAnalyticsTracker(GA_TRACKING_ID);
// gets the current screen from navigation state
function getCurrentRouteName(navigationState) {
if (!navigationState) {
return null;
}
const route = navigationState.routes[navigationState.index];
// dive into nested navigators
if (route.routes) {
return getCurrentRouteName(route);
}
return route.routeName;
}
const AppNavigator = StackNavigator(AppRouteConfigs);
export default () => (
<AppNavigator
onNavigationStateChange={(prevState, currentState) => {
const currentScreen = getCurrentRouteName(currentState);
const prevScreen = getCurrentRouteName(prevState);
if (prevScreen !== currentScreen) {
// the line below uses the Google Analytics tracker
// change the tracker here to use other Mobile analytics SDK.
tracker.trackScreenView(currentScreen);
}
}}
/>
);
Check all properties first, like
<Text>{JSON.stringify(this.props, null, 2)}</Text>
Above json array will show you current state of navigation under routeName index i.e.
this.props.navigation.state.routeName
Have you tried to define navigationOptions in your route object?
const DashboardTabNavigator = TabNavigator({
TODAY: {
screen: DashboardTabScreen
navigationOptions: {
title: 'TODAY',
},
},
})
You can also set navigationOptions to a callback that will be invoked with the navigation object.
const DashboardTabNavigator = TabNavigator({
TODAY: {
screen: DashboardTabScreen
navigationOptions: ({ navigation }) => ({
title: 'TODAY',
navigationState: navigation.state,
})
},
})
Read more about navigationOptions https://reactnavigation.org/docs/navigators/
Answer as of React Navigation v6
Depending on whether you want to trigger re-renders on value changes:
const state = navigation.getState();
or
const state = useNavigationState(state => state);
Reference:
https://reactnavigation.org/docs/use-navigation-state#how-is-usenavigationstate-different-from-navigationgetstate