I want to add event on navigation and navigate to the screen, I have this code but I don't know what's wrong.
When I set tabBarOnPress it wouldn't navigate but do the event and if I do not set it I don't know how to trigger the event.
import { createStackNavigator, createBottomTabNavigator } from 'react-
navigation';
import HomeScreen from '../screens/HomeScreen';
import LinksScreen from '../screens/LinksScreen';
import {
AdMobInterstitial,
} from 'react-native-admob';
AdMobInterstitial.setAdUnitID('ca-app-pub-2821491096541440/1777616101');
const HomeStack = createStackNavigator({
Home: HomeScreen,
});
HomeStack.navigationOptions = {
tabBarLabel: 'Apps recomendadas',
tabBarOnPress: () => {
this.somevent();
},
};
const LinksStack = createStackNavigator({
Links: LinksScreen,
});
LinksStack.navigationOptions = {
tabBarLabel: 'FAQ',
tabBarOnPress: () => {
this.somevent();
},
};
export default createBottomTabNavigator({
HomeStack,
LinksStack
},);
I had the same problem as you, but this code worked for me
tabBarOnPress: ({ navigation, defaultHandler }) => {
console.log('onPress:', navigation.state.routeName);
defaultHandler()
},
If I fail to include defaultHandler() the screen does not navigate to display the chosen route and just executes the console.log statement only
Related
I am using react-navigation, I want to open a drawer from MyProfile screen, having the options to go to EditProfile screen and Settings screen. But I can't figure out how to open a drawer when I click on MyProfile's header button.
App.js:
const MyProfileStack = createStackNavigator({
MyProfile: {
screen: profile,
navigationOptions: ({navigation}) => {
return {
title: "My Profile",
headerRight: (
<Icon type="evilicon" name="navicon" size={40}
onPress={() => navigation.dispatch(DrawerActions.openDrawer())}/>
)
};
}
}
})
const DrawerStack = createDrawerNavigator({
Edit: { screen: EditProfileStack }
Settings: { screen: SettingsStack }
})
const EditProfileStack = createStackNavigator({
EditProfile: {
screen: editProfile,
navigationOptions: ({navigation}) => {
return {
title: "Edit Profile",
headerLeft: (
<Icon type="evilicon" name="chevron-left" size={50}
onPress={() => navigation.navigate("MyProfile")}/>
)
};
}
}
});
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedStack },
Profile: { screen: MyProfileStack },
});
const MainStack = createSwitchNavigator(
{
Home: TabStack,
Drawer: DrawerStack
},
{
initialRouteName: 'Home'
}
);
const AppContainer = createAppContainer(MainStack);
Solution
You need to put your MyProfileStack in DrawerStack as below.
const DrawerStack = createDrawerNavigator({
MyProfile: { screen: MyProfileStack }
Edit: { screen: EditProfileStack }
Settings: { screen: SettingsStack }
})
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedStack },
Profile: { screen: DrawerStack },
});
const AppContainer = createAppContainer(MainStack);
You can use various combination.
Why?
SwitchNavigator resign other Screens when you switch to another one. So you cannot call drawer from the screen already resigned.
p.s: You can use navigation events if you want to refresh your screen when change the screen. Use onWillFocus.
I am using react-navigation with my react-native app. I have to put TabNavigators inside StackNavigator to use the built in header feature. See below.
app.js
const FeedScreenStack = createStackNavigator({
Feed: {
screen: feed,
navigationOptions: {
headerTitle: "Feed"
}
}
});
const ProfileScreenStack = createStackNavigator({
Feed: {
screen: profile,
navigationOptions: {
headerTitle: "My Profile"
}
}
})
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedScreenStack },
Profile: { screen: ProfileScreenStack }
});
const MainStack = createSwitchNavigator(
{
Home: TabStack,
Auth: AuthStack
},
{
initialRouteName: 'Home'
}
);
feed.js:
import React from 'react';
import { View } from 'react-native';
class feed extends React.Component {
constructor(props) {
super(props);
}
render(){
return (
<View style={{flex:1}}>
...
</View>
)
}
}
export default feed;
When clicking on profile, the app can move to profile screen. But it will not move to feed screen when clicking on feed. There are no warnings or errors, the app simply does not respond to when I click on feed. What am I doing wrong?
The problem is that you have defined repeted route names at many places, try giving different names
Do it like this
const FeedScreenStack = createStackNavigator({
FeedStack: {
screen: feed,
navigationOptions: {
headerTitle: "Feed"
}
}
});
const ProfileScreenStack = createStackNavigator({
ProfileStack: {
screen: profile,
navigationOptions: {
headerTitle: "My Profile"
}
}
})
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedScreenStack },
Profile: { screen: ProfileScreenStack }
});
const MainStack = createSwitchNavigator(
{
Home: TabStack,
Auth: AuthStack
},
{
initialRouteName: 'Home'
}
);
Trying to navigate to another screen but facing the issue. Code has been given below:
Routes.js
import { Drawer } from './Drawer';
import { ItemDetailsScreen } from '../screens/ItemDetailsScreen';
enter code here
export const App = createStackNavigator(
{
Drawer: {
screen: Drawer
},
ItemDetails: {
screen: ItemDetailsScreen
}
},
{
initialRouteName: "Drawer",
headerMode: "none"
}
)
Drawer.js
export const Drawer = createDrawerNavigator(
{
Home: { screen: ItemListScreen }
},
{
navigationOptions: () => ({
drawerLockMode: 'locked-closed'
})
initialRouteName: "Home",
drawerPosition: 'left',
contentComponent: props => <SideBar {...props} />
}
)
When trying to navigate 'ItemDetailsScreen' by calling following methods it shows me the error
onItemPress(item) {
const navigateAction = NavigationActions.navigate({
routeName: 'ItemDetailsScreen',
params: {item: item}
})
this.props.navigation.dispatch(navigateAction)
}
error is:
cannot read property 'dispatch' of undefined
I have a problem with stack navigator ... I have two navigations
tabNavigator
-> main
-> stackNavigator
-> page 1
-> page 2
So I would like when i am on page 2 and I click on main (tabNavigator) my stacknavigator reset to page 1 ...
App.js
import React, { Component } from 'react';
import { Text, Button, View } from 'react-native';
import { TabNavigator, StackNavigator, NavigationActions} from 'react-navigation';
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'PageOne'})
]
})
class PageOneScreen extends Component {
render() {
return (<View><Text> PageOne </Text><Button title="next" onPress={() => this.props.navigation.navigate('PageTwo')} /></View>);
}
}
class PageTwoScreen extends Component {
render() {
return (<View><Text> PageTwo </Text><Button title="reset" onPress={() => this.props.navigation.dispatch(resetAction)} /></View>);
}
}
class MainScreen extends Component {
render() {
return (<Text> Main </Text>);
}
}
const stackNav = StackNavigator({
PageOne: {screen: PageOneScreen},
PageTwo: {screen: PageTwoScreen}
});
const tabNav = TabNavigator({
Main: {screen: MainScreen},
Stack: {screen: stackNav}
});
export default tabNav;
But I do not manage
Use tabBarOnPress in tabNavigator which is a callback to handle tap events.
From the above code, add the navigationOption used by the Tab Navigator as coded below. Hope this will solve your problem
const tabNav = TabNavigator({
Main: {screen: MainScreen},
Stack: {
screen: stackNav,
navigationOptions: ({navigation}) => ({
tabBarOnPress: (scene, jumpToIndex) => {
navigation.dispatch(
NavigationActions.navigate({
routeName: 'Stack', //which is your route to be reset
action: NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'PageOne' }) //which is the default stack to be shown on pressing the tab
]
})
})
);
}
})
}
});
In React Native Navigation library 'react-navigation'
How could I set StackNavigator initialRouteName by AsyncStorage?
function getInitialScreen() {
AsyncStorage.getItem('initialScreen')
.then(screenName => {
return (screenName)
? screenName
: 'Login';
})
.catch(err => {});
}
const Navigator = StackNavigator({
Splash: { screen: Splash },
Login: { screen: Login },
WebPage: { screen: WebPage }
}, {
initialRouteName: getInitialScreen()
});
Changing InitialRouteName with multiple Route depending upon your requirement. I have got it working this way.
create router file import all your screens.
export a stateless function call it createRootNavigator with params as (load="<Your initial screen>")
export const createRootNavigator = (load="<Your Initial Screen>") => {
return stackNavigator({
Initialize: {
screen: Initialize,
},
Main: {
screen: Main,
},
{
initialRouteName: load
}
})
}
In your main app,
state = {
load: "<Your Initial Screen>"
}
eg:
state = {
load: "Initialize" // value is string
}
Set the state accordingly in componentDidMount() method. And finally render new layout.
render() {
const Layout = createRootNavigator(this.state.load);
<Layout />
}
The above method worked fine for me. Hope it helps somebody.
I’ve also had this problem and currently the only good solution is the following example:
const RootNavLogged = StackNavigator({
...
},{
initialRouteName : 'Home'
});
const RootNav = StackNavigator({
...
},{
initialRouteName : 'Login'
});
class App extends Component {
render(){
if (this.props.userLogged == true ){
return (
<RootNavLogged/>
)
} else {
return(
<RootNav/>
)
}
}
}
Full Solution from React Native Navigation on Restart:
const Navigator = StackNavigator({
InitialScreen: {
screen: InitialScreen
},
Splash: {
screen: Splash
},
LanguageStartup: {
screen: LanguageStartup
},
Login: {
screen: Login
},
Register: {
screen: Register
}
}, {initialRouteName: 'InitialScreen'});
export default Navigator;
My Initial Screen
import React, {Component} from 'react';
import {connect} from 'react-redux';
import * as GeneralPref from './../preferences/GeneralPref'
import Log from './../utils/Log'
import {AsyncStorage, View} from 'react-native';
import * as Pref from './../preferences/Preferences';
import {NavigationActions} from 'react-navigation'
const TAG = 'InitialScreen'
class InitialScreen extends Component {
static navigationOptions = {
header: false
};
componentWillMount() {
Log(TAG+' Mount')
const {navigate} = this.props.navigation;
GeneralPref
.getInitialScreen()
.then(value => {
Log(TAG+' Initial',value)
if (value != null) {
Log(TAG+' Initial',value)
return value
} else {
Log(TAG+' No Initial','Splash')
return 'Splash'
}
})
.then(screenName => this.props.navigation.dispatch(NavigationActions.reset({
index: 0,
actions: [NavigationActions.navigate({routeName: screenName})]
})))
.catch(err => {
Log(TAG+' Initial Error',value)
this.props.navigation.dispatch(NavigationActions.reset({
index: 0,
actions: [NavigationActions.navigate({routeName: 'Splash'})]
}))
});
}
render() {
return null;
}
}
export default InitialScreen;
then in Language Screen
changeLanguageTo(language) {
Log(TAG+'Change Language', "Change Language To: " + language.code);
// Log(TAG, 'Current State');
Log(TAG+' Language State', language);
GeneralPref.setInitialScreen('Login');
this
.props
.actions
.changeLanguage(language);
I18nManager.forceRTL(true);
// Immediately reload the React Native Bundle
RNRestart.Restart();
};