Navigate to root screen from nested stack navigator - javascript

i am new to react and trying to learn it by myself , i am facing problem in navigating user back to root screen from nested stck navigator screen .
Here is some of my classes :-
index.android.js :-
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
StatusBar,
View
} from 'react-native';
import {LoginStack} from './login/loginregisterrouter';
import {StackNavigator } from 'react-navigation';
class reactNavigationSample extends Component {
render(){
return (
<LoginStack/>
);
}
}
AppRegistry.registerComponent('MssReactDemo', () => reactNavigationSample);
loginregisterrouter :-
import React from 'react';
import {StackNavigator } from 'react-navigation';
import LoginScreen from './LoginScreen';
import RegisterScreen from './RegisterScreen';
import NavigationContainer from './navigationContainer';
export const LoginStack = StackNavigator({
LoginScreen: {
screen: LoginScreen,
navigationOptions: {
title: 'LoginScreen',
}
},
RegisterScreen: {
screen: RegisterScreen,
navigationOptions: ({ navigation }) => ({
title: 'RegisterScreen',
}),
},NavigationContainer: {
screen: NavigationContainer,
navigationOptions: ({ navigation }) => ({
title: 'NavigationContainer', header: null,
}),
},
});
Navigationcontainer.js :-
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
StatusBar,
View
} from 'react-native';
import {EasyRNRoute,} from '../parent';
import {StackNavigator } from 'react-navigation';
export default class NavigationContainer extends Component {
render(){
return (
<EasyRNRoute/>
);
}
}
parent.js :-
import React, { Component } from 'react';
import {
StyleSheet,
Text,
StatusBar,
View
} from 'react-native';
import App from './app';
import DrawerMenu from './Drawer/drawer-toolbar-android';
import BookmarkView from './Pages/bookmark';
import ClientView from './Pages/client';
import InfoView from './Pages/info';
import SettingsView from './Pages/setting';
import { DrawerNavigator, StackNavigator } from 'react-navigation';
export const stackNavigator = StackNavigator({
Info: { screen: InfoView },
Settings: {screen: SettingsView },
Bookmark: {screen: BookmarkView },
Connections: {screen: ClientView},
}, {
headerMode: 'none'
});
export const EasyRNRoute = DrawerNavigator({
Home: {
screen: App,
},
Stack: {
screen: stackNavigator
}
}, {
contentComponent: DrawerMenu,
contentOptions: {
activeTintColor: '#e91e63',
style: {
flex: 1,
paddingTop: 15,
}
}
});
Drawer-toolbar-android.js :-
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
StatusBar,
View
} from 'react-native';
import { NavigationActions } from 'react-navigation'
import { COLOR, ThemeProvider, Toolbar, Drawer, Avatar } from 'react-native-material-ui';
import Container from '../Container';
import LoginScreen from '../login/LoginScreen';
const uiTheme = {
palette: {
primaryColor: COLOR.green500,
accentColor: COLOR.pink500,
},
toolbar: {
container: {
height: 70,
paddingTop: 20,
},
},
avatar: {
container: {
backgroundColor: '#333'
}
}
};
export default class DrawerMenu extends Component {
constructor(props, context) {
super(props, context);
this.state = {
active: 'people',
};
}
handleLogoutPress = () => {
// AsyncStorage.setItem('SignedUpuser', '');
this.props
.navigation
.dispatch(NavigationActions.reset(
{
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'LoginScreen'})
]
}));
// this.props.navigation.dispatch(NavigationActions.back());
};
_setInfoActive() {
this.setState({ active: 'info' });
}
render() {
return (
<ThemeProvider uiTheme={uiTheme}>
<Container>
<StatusBar backgroundColor="rgba(0, 0, 0, 0.2)" translucent />
<Toolbar
leftElement="arrow-back"
onLeftElementPress={() => this.props.navigation.navigate('DrawerClose')}
centerElement="Menu"
/>
<View style={styles.container}>
<Drawer>
<Drawer.Header >
<Drawer.Header.Account
style={{
container: { backgroundColor: '#fafafa' },
}}
avatar={<Avatar text={'S'} />}
// accounts={[
// { avatar: <Avatar text="H" /> },
// { avatar: <Avatar text="L" /> },
// ]}
footer={{
dense: true,
centerElement: {
primaryText: 'Siddharth',
secondaryText: 'I am DONE now',
},
}}
/>
</Drawer.Header>
<Drawer.Section
style={{
label: {color: '#0000ff'}
}}
divider
items={[
{
icon: 'bookmark-border', value: 'Bookmarks',
active: this.state.active == 'bookmark',
onPress: () => {
this.setState({ active: 'bookmark' });
this.props.navigation.navigate('Bookmark');
},
},
{
icon: 'people', value: 'Connections',
active: this.state.active == 'Connection',
onPress: () => {
this.setState({ active: 'Connection' });
this.props.navigation.navigate('Connections');
},
},
]}
/>
<Drawer.Section
title="Personal"
items={[
{
icon: 'info', value: 'Info',
active: this.state.active == 'info',
onPress: () => {
this.setState({ active: 'info' });
//this.props.navigation.navigate('DrawerClose');
this.props.navigation.navigate('Info');
},
},
{
icon: 'settings', value: 'Settings',
active: this.state.active == 'settings',
onPress: () => {
this.setState({ active: 'settings' });
this.props.navigation.navigate('Settings');
},
},
{
icon: 'logout', value: 'Logout',
active: this.state.active == 'logout',
onPress: () => {
this.handleLogoutPress();
},
},
]}
/>
</Drawer>
</View>
</Container>
</ThemeProvider>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
header: {
backgroundColor: '#455A64',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
The above is the stack architecture i am using inside my application and as you can see that my Main screen is LOGIN screen and i do have option for LOGOUT from application in my Drawer(side menu). What i eaxtly want is that when user click on logout he/she should get redirected to LOGIN screen . i have googled about this and got to know about two ways of doing it , but both the ways are not working for me , may be i am using them in wrong way. so i am here to seek your help .
The two methods are :-
1)
this.props
.navigation
.dispatch(NavigationActions.reset(
{
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'LoginScreen'})
]
}));
2) this.props.navigation.dispatch(NavigationActions.back());
this question may seems silly to you but i am really stuck at this point and just want to know how can i figure this out.Any help would be greatly Appreciated!!!!
Thanks in advance.

After trying almost everything, I've found the solution that worked for me:
this.props.navigation.popToTop(); // go to the top of the stack
this.props.navigation.goBack(null); // now show the root screen

Modal StackNavigator containing a Dismissable StackNavigator
Requires: react-navigation version: 1.0.0
Goal: Navigate from App TabNavigator to Screen 1 to Screen 2 to Screen N and then directly back to App TabNavigator.
Navigation hierarchy:
RootNavigator StackNavigator {mode: 'modal'}
App TabNavigator
TabA Screen
TabB Screen
TabC Screen
ModalScreen Screen
ModalStack DismissableStackNavigator
Screen 1 ModalStackScreen
Screen 2 ModalStackScreen
Screen N ModalStackScreen
Demo
package.json
{
"name": "HelloWorld",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"react": "16.0.0-alpha.6",
"react-native": "0.44.0",
"react-navigation": "^1.0.0"
},
"devDependencies": {
"babel-jest": "20.0.3",
"babel-preset-react-native": "1.9.2",
"jest": "20.0.3",
"react-test-renderer": "16.0.0-alpha.6"
},
"jest": {
"preset": "react-native"
}
}
index.ios.js (or index.android.js)
import React from 'react'
import {
AppRegistry,
Button,
Text,
View
} from 'react-native'
import {
StackNavigator,
TabNavigator
} from 'react-navigation'
class TabA extends React.Component {
state = {
startScreen: 'none',
returnScreen: 'none'
}
render () {
return (
<View style={{ padding: 40, paddingTop: 64 }}>
<Text style={{ fontSize: 20 }}>{this.constructor.name}</Text>
<Text>startScreen: {this.state.startScreen}</Text>
<Text>returnScreen: {this.state.returnScreen}</Text>
<Button
title="Open ModalScreen"
onPress={() => this.props.navigation.navigate('ModalScreen', {
startScreen: this.constructor.name,
setParentState: (state) => this.setState(state)
})}
/>
<Button
title="Open ModalStack"
onPress={() => this.props.navigation.navigate('ModalStack', {
startScreen: this.constructor.name,
setParentState: (state) => this.setState(state)
})}
/>
</View>
)
}
}
class TabB extends TabA {}
class TabC extends TabA {}
class ModalScreen extends React.Component {
render () {
const {
startScreen,
setParentState
} = this.props.navigation.state.params
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 20 }}>{this.constructor.name}</Text>
<Button
title="Close"
onPress={() => {
setParentState({
startScreen,
returnScreen: this.constructor.name
})
this.props.navigation.goBack()
}}
/>
</View>
)
}
}
const DismissableStackNavigator = (routes, options) => {
const StackNav = StackNavigator(routes, options)
return class DismissableStackNav extends React.Component {
static router = StackNav.router
render () {
const { state, goBack } = this.props.navigation
const screenProps = {
...this.props.screenProps,
dismissStackNav: () => goBack(state.key)
}
return (
<StackNav
screenProps={screenProps}
navigation={this.props.navigation}
/>
)
}
}
}
class ModalStackScreen extends React.Component {
render () {
const screenNumber = this.props.navigation.state.params && this.props.navigation.state.params.screenNumber || 0
const {
startScreen,
setParentState
} = this.props.navigation.state.params
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 20 }}>{this.constructor.name + screenNumber}</Text>
<View style={{
flexDirection: 'row',
justifyContent: 'space-between'
}}>
<Button
title={screenNumber === 0 ? "Close" : "Back"}
onPress={() => this.props.navigation.goBack(null)}
/>
<Button
title="Save"
onPress={() => {
setParentState({
startScreen,
returnScreen: this.constructor.name + screenNumber
})
this.props.screenProps.dismissStackNav()
}}
/>
<Button
title="Next"
onPress={() => this.props.navigation.navigate('ModalStackScreen', {
screenNumber: screenNumber + 1,
startScreen,
setParentState
})}
/>
</View>
</View>
)
}
}
const TabNav = TabNavigator(
{
TabA: {
screen: TabA
},
TabB: {
screen: TabB
},
TabC: {
screen: TabC
}
}
)
const ModalStack = DismissableStackNavigator(
{
ModalStackScreen: {
screen: ModalStackScreen
}
},
{
headerMode: 'none'
}
)
const RootStack = StackNavigator(
{
Main: {
screen: TabNav,
},
ModalScreen: {
screen: ModalScreen,
},
ModalStack: {
screen: ModalStack
}
},
{
mode: 'modal',
headerMode: 'none'
}
)
class App extends React.Component {
render () {
return <RootStack />
}
}
AppRegistry.registerComponent('HelloWorld', () => App)
Previous Answer
This solution is a sledgehammer. It causes the screen of the default tab in the TabNavigator to unmount and then mount again. If the Screen a tab launching the Modal with the StackNavigator passes some callbacks to update it's state, these callbacks will be called when the Screen is unmounted.
The solution was to add key: null to the reset object:
this.props.navigation.dispatch(NavigationActions.reset({
index: 0,
key: null,
actions: [
NavigationActions.navigate({ routeName: 'App'})
]
}))
I was tipped off by this comment.
(FYI - I got here via your comment asking for help.)

As per react navigation doc you can go to any stack by following ways:
check the following link for more details
React-navigation stack action link
1. import { StackActions, NavigationActions } from 'react-navigation';
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Profile' })],
});
this.props.navigation.dispatch(resetAction);
If you have a stack for profile then you can also go through like this check following link nested react navigation
import { NavigationActions } from 'react-navigation';
const navigateAction = NavigationActions.navigate({
routeName: 'Profile',
params: {},
action: NavigationActions.navigate({ routeName: 'SubProfileRoute' }),
});
this.props.navigation.dispatch(navigateAction);

(React Navigation 5.x) I had the problem of conditionally rendering the Screens like the example in
"https://reactnavigation.org/docs/en/auth-flow.html" As I understand, meant that the Stack navigators were not "rendered" and thus are not able to find each other. What I did was the below and in the logout page:
navigation.replace('SplashScreen')
My logic was: SplashScreen (Check for AsyncStorage Token),
if (token){
navigation.navigate('App')
}else{
navigation.navigate('StartScreen')
}
In StartScreen, just navigate to Signin or Register where you go back to App if login is successful.
As a reference,
function AppBottomNavigator(){
return(
<AppNavigator.Navigator
initialRouteName={'Home'} ...}>
<AppNavigator.Screen name='A' component={ScreenA}/>
<AppNavigator.Screen name='B' component={ScreenB}/>
<AppNavigator.Screen name='C' component={ScreenC}/>
<AppNavigator.Screen name='D' component={ScreenD}/>
<AppNavigator.Screen name='E' component={ScreenE}/>
</AppNavigator.Navigator>
)
}
export default App stuff...
...return(
<AuthContext.Provider value={authContext}>
<NavigationContainer>
<AuthStack.Navigator screenOptions={{headerShown:false}}>
<>
<AuthStack.Screen name='SplashScreen' component={SplashScreen}/>
<AuthStack.Screen name='StartScreen' component={StartScreen} />
<AuthStack.Screen name='SignIn' component={SignIn} />
<AuthStack.Screen name='Register' component={Register} />
<AuthStack.Screen name='App' component={AppBottomNavigator}/>
</>
</AuthStack.Navigator>
</NavigationContainer>
</AuthContext.Provider>
)
I am also quite new to this but it worked so if someone else has a safer/tidier/general solution, I would quite like to know, too.

Related

How to navigate pages with React Navigator

Having trouble moving pages in React Navigator, it worked fine when we had homeStack and would just run through an object but now that we're trying to introduce a stationary button in the header that moves to another page it is running into problem. We still move just fine when we go from first to second page, but I think we're missing something.
OnPress is working when we press the folder icon as we console logged it, but it simply takes us back to our starting screen rather than to the screen we want to get to. I've tried to share the code needed but let me know if other pages are needed.
Below is our Header component, you can see where we're trying to onPress and then navigate.
import React from 'react';
import {StyleSheet, Text, View} from 'react-native';
import {MaterialIcons} from '#expo/vector-icons';
import History from '../History'
import { NavigationContainer, StackActions } from "#react-navigation/native";
import { createNativeStackNavigator } from 'react-navigation-stack';
export default function Header({ navigation }){
const historyFolder = () => {
navigation.navigate('History')
}
return(
<View style={styles.header}>
<View>
<Text style={styles.headerText}></Text>
</View>
<MaterialIcons name='folder' size={28} onPress={historyFolder} style={styles.icon}></MaterialIcons>
</View>
)
}
const styles = StyleSheet.create({
header: {
width: '100%',
height: '100%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
headerText: {
fontWeight: 'bold',
fontSize: 20,
color: '#333',
letterSpacing:1,
},
icon:{
position: 'absolute',
right: 16,
}
})
This is the History page that we're aiming to get to.
import { StyleSheet, Text, View, FlatList, SafeAreaView, Image } from 'react-native'
import Card from './shared/Card';
import React from 'react';
import { NavigationContainer, StackActions } from "#react-navigation/native";
import { createNativeStackNavigator } from 'react-navigation-stack';
export default function History({navigation}) {
const present = [{
id: 1,
name: 'PresentOne',
slug: 'PresentOne Slug',
image: require('../assets/present.jpeg')
},
{
id:2,
name: 'PresentTwo',
slug: 'PresentTwo Slug',
image: require('../assets/present2.jpeg')
},
{
id:3,
name: 'PresentThree',
slug: 'PresentThree Slug',
image: require('../assets/present3.jpeg')
},
{
id:4,
name: 'PresentFour',
slug: 'PresentFour Slug',
image: require('../assets/present4.jpeg')
},
{
id:5,
name: 'PresentFive',
slug: 'PresentFive Slug',
image: require('../assets/present5.jpeg')
},
];
const onePresent = ( { item } ) => (
<Card>
<View style={styles.item}>
<View style={styles.avatarContainer}>
<Image source = {item.image} style={styles.avatarContainer}/>
</View>
<Text style={styles.name}> {item.name}</Text>
<Text style={styles.slug}>{item.slug}</Text>
</View>
</Card>
)
const headerComponent = () => {
return <Text style={styles.listHeadline}>Presents</Text>
}
const itemSeperator = () => {
return <View style = {styles.seperator}/>
}
return (
<View>
<FlatList
ListHeaderComponentStyle={styles.listHeader}
ListHeaderComponent={headerComponent}
data = { present }
renderItem = { onePresent }
ItemSeperatorComponent = { itemSeperator }
ListEmptyComponent = { <Text>Empty</Text>}
/>
</View>
);
}
const styles = StyleSheet.create({
slug:{
transform: [{translateX: -100}],
// alignContent: 'center',
flexDirection: 'column',
alignItems: 'center',
},
name:{
transform: [{translateY: -30},{translateX: 10}],
fontSize: 20,
},
listHeadline:{
color:'#333',
fontSize: 21,
fontWeight: 'bold',
},
item: {
flex:1,
flexDirection:'row',
alignItems:'center',
paddingVertical:13,
},
avatarContainer:{
backgroundColor:'#D9D9D9',
borderRadius:100,
height:89,
width:89,
justifyContent:'center',
alignItems: 'center',
margin:10,
},
listHeader:{
height:55,
alignItems:'center',
justifyContent: 'center'
},
seperator: {
height: 1,
width: '100%',
backgroundColor: '#CCC',
}
})
And this is the homeStack we're running the page from.
import React from 'react';
import {StyleSheet, View, Text} from 'react-native';
import { createStackNavigator } from 'react-navigation-stack'
import { createAppContainer } from 'react-navigation'
import PositiveCollectForm from '../Components/PositiveCollectForm';
import NegativeCollectForm from '../Components/NegativeCollectForm';
import Swipe from '../Components/Swipe';
import History from '../Components/History';
import Header from '../Components/shared/Header';
const screens = {
PositiveCollectForm: {
screen: PositiveCollectForm,
navigationOptions: ({ navigation }) => {
return {
// headerTitle: () => <Header navigation={navigation} />
}
}
},
Swipe: {
screen: Swipe,
navigationOptions: {
title: '',
headerTitle: () => <Header navigation={navigation} />
},
},
History: {
screen: History,
navigationOptions: {
title: '',
headerStyle: {backgroundColor: '#555'}
}
},
}
const HomeStack = createStackNavigator(screens);
export default createAppContainer(HomeStack);

View config getter callback for component 'H' must be a function (received undefined)

Error is:
Invariant Violation: View config getter callback for component 'H' must be a function (received undefined)
I'm using react-native to make application and error happens when I clicked login button in MainLogin.js file. (It has to move to mainpage when clicking login button in login page)
I searched a lot but cannot know what is component 'H'.
attatched index.js (src/screens/index.js) and MainLogin.js (src/screens/MainLogin.js)
<index.js>
import React from 'react';
import {
Text
} from 'react-native';
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import { createBottomTabNavigator } from "react-navigation-tabs";
import LoginScreen from './MainLogin';
import HomeScreen from './MainPage';
import DiaryScreen from './Diarymemo';
import StatScreen from './MoodStatistics';
import CommuScreen from './Community';
import StoreScreen from './Store';
const HomeStack = createStackNavigator(
{
HomeScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Home'}),
}
);
const DiaryStack = createStackNavigator(
{
DiaryScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Diary'}),
}
);
const StatStack = createStackNavigator(
{
StatScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Stat'}),
}
);
const CommunityStack = createStackNavigator(
{
CommuScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Network'}),
}
);
const StoreStack = createStackNavigator(
{
StoreScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Store'}),
}
);
const TabNavigator = createBottomTabNavigator(
InitialRouteName = 'Home',
{
Diary: DiaryStack,
Stat: StatStack,
Home: HomeStack,
Network: CommunityStack,
Store: StoreStack,
},
{
defaultNavigationOptions: ({navigation}) => ({
tabBarIcon: ({focused, horizontal, tintColor}) => {
const {routeName} = navigation.state;
let icon = "▲";
if(routeName === 'Diary'){
icon = "📓";
} else if(routeName === 'Stat'){
icon = "📊"
} else if(routeName === 'Home'){
icon = "🍎"
} else if(routeName === 'Network'){
icon = "👫"
} else if(routeName === 'Store'){
icon = "🛍"
}
// can use react-native-vector-icons
// <Icon name={iconName} size={iconSize} color={iconColor} />
return <Text style={{color: focused && "#46c3ad" || "#888"}}>{icon}</Text>
}
}),
lazy: false,
tabBarOptions: {
activeTintColor: "#46c3ad",
inactiveTintColor: "#888",
},
}
);
const AppStack = createStackNavigator(
{
LoginScreen: LoginScreen,
TabNavigator: {
screen: TabNavigator,
navigationOptions: ({navigation}) => ({
headerShown: false,
}),
},
}
);
export default createAppContainer(AppStack);
<MainLogin.js>
import React, {Component} from 'react';
import {
View,
Text,
TextInput,
TouchableOpacity,
StyleSheet
} from 'react-native';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
export default class LoginScreen extends Component{
static navigationOptions = {
headerShown: false,
};
_doLogin(){
// do something
this.props.navigation.replace('TabNavigator')
}
render(){
return (
<View style={styles.container}>
<View style={styles.titleArea}>
<Text style={styles.title}>MoodiBuddy</Text>
</View>
<View style={styles.formArea}>
<TextInput
style={styles.textForm}
placeholder={"ID"}/>
<TextInput
style={styles.textForm}
placeholder={"Password"}/>
</View>
<View style={styles.buttonArea}>
<TouchableOpacity
style={styles.button}
onPress={this._doLogin.bind(this)}>
<Text style={styles.buttonTitle}>Login</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
paddingLeft: wp('10%'),
paddingRight: wp('10%'),
justifyContent: 'center',
},
titleArea: {
width: '100%',
padding: wp('10%'),
alignItems: 'center',
},
title: {
fontSize: wp('10%'),
},
formArea: {
width: '100%',
paddingBottom: wp('10%'),
},
textForm: {
borderWidth: 0.5,
borderColor: '#888',
width: '100%',
height: hp('5%'),
paddingLeft: 5,
paddingRight: 5,
marginBottom: 5,
},
buttonArea: {
width: '100%',
height: hp('5%'),
},
button: {
backgroundColor: "#46c3ad",
width: "100%",
height: "100%",
justifyContent: 'center',
alignItems: 'center',
},
buttonTitle: {
color: 'white',
},
})

navigator has both navigation and container props error in React Native

So Important : my project was working , bat when i copied them to my backup folder and used after deleting files!!, i got navigation error:
Error: This navigator has both navigation and container props, so it is unclear if it should own its own state. Remove props: "theme" if the navigator should get its state from the navigation prop. If the navigator should maintain its own state, do not pass a navigation prop.
here is my App.js codes:
import { createAppContainer } from "react-navigation"
import AppNavigator from './app/Navi/Navigate'
const AppContainer = createAppContainer(AppNavigator);
export default class App extends React.Component {
render() {
return <AppContainer />
}
}
Where i call AppNavigator from Navigate.js:
const AppNavigator = createStackNavigator({
indexPage : Index,
loginPage : Login,
homePage : TabNavigator
},
{
initialRouteName: "indexPage",
headerMode: 'none',
navigationOptions: {
headerVisible: false,
}
});
export default AppNavigator;
and index.js where error is there (error says it is in line 29 that refers to line 40) :
export default class Index extends React.Component{
componentDidMount(){
this.checker();
}
transfer = (page) => {
if(page == 'Home')
this.props.navigation.navigate('homePage');
else
this.props.navigation.navigate('loginPage');
}
checker = () => {
AsyncStorage.getItem('LoginBoolean')
.then((value) => {
if(value == 'yes')
this.transfer('Home');
else
this.transfer('Login');
})
.catch((error) =>
console.log(error)
);
}
render(){
some rendering tags!
}
}
and no idea what is going on!
Edited
the TabNavigator Compeletly Codes:
that const rednderNav and customTabs are some customization for tab ui
import { createBottomTabNavigator, createAppContainer } from 'react-navigation';
import Home from '../Home/home'
import LogOut from '../Logging/logout'
import Search from '../Route/Search'
import Poll from '../Poll/Poll'
import Signate from '../sign/signate'
const renderNav = (name, tintColor) => (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Icon name={name} size={15} style={{color: tintColor}} />
</View>
)
const customTabs = ({ navigation }) => ({
tabBarIcon: ({tintColor }) => {
const { routeName } = navigation.state;
if (routeName === 'LogOut') {
return renderNav('md-log-out', tintColor);
} else if (routeName === 'Home') {
return renderNav('md-planet', tintColor);
} else if (routeName === 'Route') {
return renderNav('md-compass', tintColor);
} else if (routeName === 'Poll') {
return renderNav('ios-checkmark-circle', tintColor);
} else if (routeName === 'Sign') {
return renderNav('hand', tintColor);
}
}
});
const TabNavigator = createBottomTabNavigator({
LogOut : LogOut,
Route : Search,
Home : Home,
Poll : Poll,
Sign : Signate
},
{
defaultNavigationOptions: customTabs,
animationEnabled: true,
swipeEnabled: true,
tabBarPosition: 'bottom',
initialRouteName: 'Poll',
tabBarOptions: {
showLabel: false,
activeTintColor: 'yellow',
inactiveTintColor: '#fff',
style:{
borderTopColor: '#ccc',
borderTopWidth: 3,
backgroundColor:'#191919',
height: 50,
},
activeTabStyle: {
backgroundColor: 'white',
borderBottomWidth: 40,
borderColor: '#6C1D7C'
}
},
});
export default createAppContainer(TabNavigator);
From what I see, you are returning a AppContainer in your TabNavigator file, you should only have one AppContainer for all the application.
So the perfect way can be to return directly the Tabnavigator
export default TabNavigator;
I resolved as follows
original:
export default createAppContainer( createBottomTabNavigator( {
modified:
export default createBottomTabNavigator( {

React-Native Welcome Screen on first login

I am developing a React-Native app in which I want to include a Welcome Screen that shows up after the user logs in, but only on the first time. I have already developed the Welcome Screen with React-Native-App-Intro-Slider and it works fine, but it shows up every time the user opens the app.
This is the code I have at the moment. This is the Welcome.js code:
import { StyleSheet, View, Text, Image, I18nManager, Dimensions } from 'react-native';
import AppIntroSlider from 'react-native-app-intro-slider';
import { TouchableRipple } from 'react-native-paper'
import FastImage from 'react-native-fast-image';
import Icon from 'react-native-vector-icons/FontAwesome5'
import styles from './Welcome.styles';
I18nManager.forceRTL(false);
const slides = [
{
key: 'k1',
title: '',
text:
'',
video: {
'id': 'k1',
'name': '',
'externalUrl': '',
'link': '',
'type': 'video',
'uuid': 'external',
'cover_url': '',
'title-human': '',
'brand-human': '',
},
image: require('../../assets/images/logo.png')
},
{
key: 'k2',
title: 'Step 1:',
text: '',
video: {
'id': 'k2',
'name': '',
'externalUrl': '',
'link': '',
'type': 'video',
'uuid': 'external',
'cover_url': '',
'title-human': '',
'brand-human': '',
},
footer: ''
},
{
key: 'k3',
title: 'Step 2:',
text: 'Connect your music through your speakers',
video: {
'id': 'k3',
'name': '',
'externalUrl': '',
'link': '',
'type': 'video',
'uuid': 'external',
'cover_url': '',
'title-human': '',
'brand-human': '',
},
}, {
key: 'k4',
title: '',
text: '',
video: {
'id': 'k4',
'name': '',
'externalUrl': '',
'link': '',
'type': 'video',
'uuid': 'external',
'cover_url': '',
'title-human': '',
'brand-human': '',
},
},
{
key: 'k5',
title: 'And lastly...',
image: require('../../assets/images/logo.png'),
text: '',
footer: ''
}
];
export default class Welcome extends React.Component {
constructor(props) {
super(props);
this.state = {
show_Main_App: false
}
}
static navigationOptions = { header: null }
on_Done_all_slides = () => {
this.setState({ show_Main_App: true });
};
on_Skip_slides = () => {
this.setState({ show_Main_App: true });
};
_renderItem = ({ item }) => (
<View style={styles.mainContent}>
<Text style={styles.title}>{item.title}</Text>
{item.image == undefined ? (
<>
<View style={styles.videoContainer}>
<FastImage style={styles.videoImage} resizeMode='cover' source={{ uri: item.video.cover_url }} />
<View style={styles.videoDetailsContainer}>
<View style={styles.videoTagContainer}>
<Text style={styles.videoTagText}> </Text>
</View>
<View style={styles.featuredVideoButtonsContainer}>
<TouchableRipple
onPress={() => this.props.navigation.navigate({ routeName: 'VideoPlayer', key: 'videoPlayer', params: { 'item': item.video } })}
rippleColor='rgba(0, 0, 0, .32)'
>
<View style={styles.videoPlayButton}>
<Icon style={styles.videoPlayButtonIcon} name='play-circle' size={100} color='#fff' />
<Text style={styles.videoPlayButtonText}>Play</Text>
</View>
</TouchableRipple>
</View>
</View>
</View>
<Text style={styles.text}>{item.text}</Text>
</>
) : (
<>
<Image source={item.image} style={styles.image} resizeMode='contain' />
<View>
<Text style={styles.text}>
{item.text}
</Text>
<Text style={styles.text}>
{item.footer}
</Text>
</View>
</>
)}
</View>
);
render() {
if (this.state.show_Main_App) {
return (
this.props.navigation.replace('Dashboard')
);
} else {
return (
<AppIntroSlider
renderItem={this._renderItem}
slides={slides}
onDone={this.on_Done_all_slides}
showSkipButton={true}
onSkip={this.on_Skip_slides} />
);
}
}
}
As I said, this works exactly as intended. However, it shows up every time. This is my App.js code:
import { createStackNavigator, createAppContainer, createBottomTabNavigator } from 'react-navigation'
import { View, StatusBar, Text } from 'react-native'
// import FontAwesome from 'react-native-vector-icons/FontAwesome5'
import IconFontawesome from 'react-native-vector-icons/FontAwesome'
import IconMaterial from 'react-native-vector-icons/MaterialCommunityIcons'
import { MenuProvider } from 'react-native-popup-menu';
// screens
import Splashscreen from './src/screens/Splashscreen/Splashscreen'
import ProfileSetup from './src/screens/ProfileSetup/ProfileSetup'
import UserCreation from './src/screens/UserCreation/UserCreation'
import Login from './src/screens/Login/Login'
import Signup from './src/screens/Signup/Signup'
import VideoPlayer from './src/screens/VideoPlayer/VideoPlayer'
import VideoProfile from './src/screens/VideoProfile/VideoProfile'
import AudioProfile from './src/screens/AudioProfile/AudioProfile'
import ForgotPassword from './src/screens/ForgotPassword/ForgotPassword'
import Welcome from './src/screens/Welcome/Welcome'
import WhoWatching from './src/screens/WhoWatching/WhoWatching'
// Tabs
import MenuScreen from './src/screens/TabScreens/MenuScreen/MenuScreen'
import HomeScreen from './src/screens/TabScreens/HomeScreen/HomeScreen'
// import DownloadScreen from './src/screens/TabScreens/DownloadScreen/DownloadScreen' // avega : replaced with devices screen
import DeviceScreen from "./src/screens/TabScreens/DeviceScreen/DeviceScreen";
import SearchScreen from './src/screens/TabScreens/SearchScreen/SearchScreen'
// Menu Screens
import AccountScreen from './src/screens/TabScreens/MenuScreen/AccountScreen/AccountScreen'
import AppSettingsScreen from './src/screens/TabScreens/MenuScreen/AppSettingsScreen/AppSettingsScreen'
import CellularDataUsageScreen from './src/screens/TabScreens/MenuScreen/AppSettingsScreen/CellularDataUsageScreen/CellularDataUsageScreen'
import VideoQualityScreen from './src/screens/TabScreens/MenuScreen/AppSettingsScreen/VideoQualityScreen/VideoQualityScreen'
import HelpScreen from './src/screens/TabScreens/MenuScreen/HelpScreen/HelpScreen'
import ManageProfilesScreen from './src/screens/TabScreens/MenuScreen/ManageProfilesScreen/ManageProfilesScreen'
import MyListScreen from './src/screens/TabScreens/MenuScreen/MyListScreen/MyListScreen'
import PrivacyScreen from './src/screens/TabScreens/MenuScreen/PrivacyScreen/PrivacyScreen'
import configureStore from "./src/state/store";
import {Provider} from "react-redux";
import {Root} from "native-base";
import DeviceProfile from "./src/screens/DeviceProfile/DeviceProfile";
import DeviceEnroll from "./src/screens/DeviceEnroll/DeviceEnroll";
const DashboardTabNavigator = createBottomTabNavigator(
{
HomeScreen: HomeScreen,
SearchScreen: SearchScreen,
DeviceScreen: DeviceScreen,
MenuScreen: MenuScreen
},
{
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, horizontal, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'MenuScreen') {
iconName = `menu`
} else if (routeName === 'HomeScreen') {
iconName = `home`
} else if (routeName === 'DeviceScreen') {
iconName = `television`;
} else if (routeName === 'SearchScreen') {
iconName = `thermometer`
}
// return <IconFontawesome name={iconName} size={30} color={focused ? '#fff' : '#c0d3d6'} />
return <IconMaterial name={iconName} size={30} color={focused ? '#fff' : '#c0d3d6'} />
},
tabBarLabel: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let labelName;
if (routeName === 'MenuScreen') {
labelName = `Menu`
} else if (routeName === 'HomeScreen') {
labelName = `Showcase`
} else if (routeName === 'DeviceScreen') {
labelName = `Devices`
} else if (routeName === 'SearchScreen') {
labelName = `Store`
}
return <Text style={focused ? { textAlign: 'center', fontSize: 11, color: '#fff', fontWeight: '600', marginTop: -5, marginBottom: 5 } : { textAlign: 'center', fontSize: 11, marginTop: -5, marginBottom: 5, color: '#C0D3D6' }}>{labelName}</Text>
}
}),
tabBarOptions: {
activeTintColor: '#ff3402',
inactiveTintColor: '#eaeaea',
style: {
backgroundColor: '#00A5AC',
height: 65
},
labelStyle: {
color: '#fff'
}
},
initialRouteName: 'HomeScreen',
navigationOptions: {
header: null
}
}
)
const AppNavigator = createStackNavigator(
{
Splashscreen: Splashscreen,
UserCreation: UserCreation,
Login: Login,
Signup: Signup,
ProfileSetup: ProfileSetup,
Dashboard: DashboardTabNavigator,
Account: AccountScreen,
AppSettings: AppSettingsScreen,
VideoQuality: VideoQualityScreen,
CellularDataUsage: CellularDataUsageScreen,
Help: HelpScreen,
ManageProfiles: ManageProfilesScreen,
MyList: MyListScreen,
Privacy: PrivacyScreen,
VideoPlayer: VideoPlayer,
VideoProfile: VideoProfile,
AudioProfile: AudioProfile,
//AudioPlayer: AudioPlayer
ForgotPassword: ForgotPassword,
WhoWatching: WhoWatching,
DeviceProfile: DeviceProfile,
DeviceEnroll: DeviceEnroll,
Welcome: Welcome
},
{
initialRouteName: 'Splashscreen',
navigationOptions: {
header: null
}
}
);
const AppContainer = createAppContainer(AppNavigator)
export default class App extends React.Component {
store = configureStore();
render () {
return (
<Provider store={this.store}>
<Root>
<MenuProvider>
<View style={{ flex: 1 }}>
<AppContainer />
<StatusBar translucent backgroundColor='transparent' barStyle='light-content' />
</View>
</MenuProvider>
</Root>
</Provider>
)
}
}
As you can see the first page is a Splashscreen, that then should lead to the guided tour. This is the Splashscreen.js code:
import { View, Image, ActivityIndicator } from 'react-native'
import styles from './Splashscreen.styles'
import AuthHelperMethods from "../../api/auth-helper-methods";
export default class Splashscreen extends Component {
static navigationOptions = { header: null }
componentDidMount () {
setTimeout(() => {
AuthHelperMethods.loggedIn().then((isLoggedIn) => {
if (isLoggedIn) {
this.props.navigation.replace('Welcome')
} else {
this.props.navigation.replace('UserCreation')
}
})
}, 500)
}
state={
loading: true
};
render () {
return (
<View style={styles.container}>
<Image style={styles.logo} resizeMode='contain' source={require('../../assets/images/logo.png')} />
<ActivityIndicator size={50} color='#00b2ba' />
</View>
)
}
}
I'm not really sure how to start conceptualizing the idea of this component only showing up either on first-time login, or at least once per login instead of every time the app is used.
Any ideas how to go about it?
You can simply use localStorage. You will have to do some conditional rendering. Whenever user launches the app, you will have to do something like localStorage.setItem('firstTime', false). So, next time when user launches the app, all you need is check if localStorage.getItem('firstTime') === false, if it is false, you render your login page.
The easiest way is probably using asyncStorage (https://facebook.github.io/react-native/docs/asyncstorage)
After installing it import it like:
import AsyncStorage from '#react-native-community/async-storage';
or
import {AsyncStorage} from 'react-native' //Deprecated, will be removed in the future
After you've showed the user the welcome screen, store the data inside asyncStorage:
storeData = async () => {
try {
await AsyncStorage.setItem('welcomeScreenSeen', 'true')
} catch (e) {
// saving failed
}
}
After that, ever login would check that variable and if it's false, just skip your welcomeScreen.
then inside your isLoggedInIf it would be:
if (isLoggedIn) {
this.props.navigation.replace(this.getData("welcomeScreenSeen")?'ScreenDifferentFromWelcome':'Welcome')
}
where getData would be:
getData = async (key) => {
try {
const value = await AsyncStorage.getItem(key)
return value
} catch(e) {
// error reading value
}
You can use Shared Preferences to check if it is the first login.
Simply store a boolean like showWelcomeScreen when the welcome screen was shown.
On startup you can check the shared preferences and decide wheter to show or not to show the screen.
For more information check: Shared Preferences

undefined is not an object (evaluating '_this3.props.navigation.navigate')

Problem with stack navigation between the screens.
I am displaying data on my 'SveKategorije' screen.
It's basically categories buttons, when i click on button i just want to show another screen for now, but it is not working for some reason.
When i put onPress={() => this.props.navigation.navigate('screenname')}
it gives me this
error
I am using (react-native - 0.57.7)
Here is router.js code (where i declare my routes)
import React from 'react';
import { View, Text, Button } from "react-native";
import { createBottomTabNavigator, createStackNavigator } from "react-navigation";
import { Icon } from 'react-native-elements';
//TABS
import Categories from '../tabs/categories';
import Home from '../tabs/home';
import Me from '../tabs/me';
//screens for CATEGORIES
import ViceviPoKategoriji from '../components/Ispis/ViceviPoKategoriji';
//CATEGORIES STACK
export const categoriesFeedStack = createStackNavigator({
SveKategorije: {
screen: Categories,
navigationOptions: {
title: 'KATEGORIJE',
},
},
ViceviPoKategoriji: {
screen: ViceviPoKategoriji,
}
});
//TABS
export const Tabs = createBottomTabNavigator({
Categories: {
screen: categoriesFeedStack,
navigationOptions: {
title: 'Kategorije',
label: 'Kategorije',
tabBarIcon: ({ tintColor }) => <Icon name="list" size={35} color={tintColor} />,
}
},
Home: {
screen: Home,
navigationOptions: {
title: 'Pocetna',
label: 'Kategorije',
tabBarIcon: ({ tintColor }) => <Icon name="home" size={35} color={tintColor} />,
}
},
Me: {
screen: Me,
navigationOptions: {
title: 'Profil',
label: 'Kategorije',
tabBarIcon: ({ tintColor }) => <Icon name="account-circle" size={35} color={tintColor} />,
}
},
},
{
initialRouteName: "Home",
showIcon: true
},
);
Here is 'SveKategorije' screen
import React from 'react';
import { StyleSheet, Text, View, ActivityIndicator, ScrollView, Button } from 'react-native';
import { createStackNavigator, createAppContainer, StackNavigator, navigate } from 'react-navigation';
export default class SveKategorije extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null
}
}
componentDidMount() {
return fetch('http://centarsmijeha.com/api/allCategories')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data,
})
})
.catch((error) => {
console.log(error)
});
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
)
} else {
let data = this.state.dataSource.map((val, key) => {
return (
<View key={key} style={styles.item}>
<Button
onPress={() => this.props.navigation.navigate('ViceviPoKategoriji')}
title={val.categoryName}
/>
</View>
);
});
return (
<ScrollView>
{data}
</ScrollView >
);
}
}
}
//CSS
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
width: '100%'
},
item: {
flex: 1,
alignSelf: 'stretch',
width: '100%',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center'
}
});
and here is 'ViceviPoKategoriji' screen ( the screen that should be displayed on click of any buttons from 'SveKategorije' screen )
import React from 'react';
import { StyleSheet, Text, View, ActivityIndicator, ScrollView } from 'react-native';
export default class ViceviPoKategoriji extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null,
}
}
componentDidMount() {
return fetch('http://centarsmijeha.com/api/jokesByCategory/16')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data,
})
})
.catch((error) => {
console.log(error)
});
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
)
} else {
let data = this.state.dataSource.map((val, key) => {
return <View key={key} style={styles.item}><Text>{val.jokeText}</Text></View>
});
return (
<ScrollView>
{data}
</ScrollView >
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
item: {
flex: 1,
alignSelf: 'stretch',
marginTop: 50,
marginRight: '15%',
marginLeft: '15%',
width: '70%',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center',
borderBottomWidth: 1,
borderBottomColor: '#eee'
}
});
React-navigation is props based navigation.
I think your component don't have navigation props.
Please check whether your component have navigation props.
do
render() {
console.log(this.props.navigation)
// or debugger
return (
If result of console.log is undefined, then add 'import SveKategorije' to your routing file.
You have to do few more setups for navigating from the component.You can get access to a navigator through a ref and pass it to the NavigationService which we will later use to navigate.
https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html
In my case I accidentally used this.props.navigation inside functional component. If any one made a mistake like this, will check u r code once again.

Categories

Resources