React Native Redux conditional LoggedIn render causes race condition - react-native

So I am pretty new to React Native and completely new to redux. I have created an auth flow using a conditional React Navigation render that works apart from giving an error, I believe is causedby a race condition. What happens that it checks if a user is signed in and renders based on if they are or not. But if the user is already logged in, it starts to render the LoginScreen, detects they are logged in, then tries to re-render, causing the following error:
"Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the Icon component."
My main component looks like this:
import React, { Component } from "react";
import { StyleSheet, Text, View, AsyncStorage } from "react-native";
import { connect, Provider } from "react-redux";
import Reactotron from "reactotron-react-native";
import { logIn } from "../actions";
import { SignedIn, SignedOut } from "../components/Nav";
import { isSignedIn } from "../components/Auth";
import LoginScreen from "../containers/LoginScreen";
class RootApp extends Component {
async checkSignedIn() {
res = await isSignedIn();
if (res != false) {
expires = String(res.expires);
this.props.logIn(res.fbToken, expires);
} else {
console.log("Not logged in");
}
}
async componentWillMount() {
await this.checkSignedIn();
}
render() {
if (this.props.auth.signedIn == true) {
return <SignedIn />;
} else {
return <SignedOut />;
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
fontSize: 96
}
});
const mapStateToProps = state => {
return {
auth: state.auth
};
};
const mapDispatchToProps = dispatch => {
return {
logIn: fbToken => {
dispatch(logIn(fbToken, expires));
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(RootApp);
The Nav looks like
import React, { Component } from "react";
import { TabNavigator, StackNavigator } from "react-navigation";
import Tasks from "../screens/Tasks";
import Home from "../screens/Home";
import Message from "../screens/Message";
import Profile from "../screens/Profile";
//import WelcomeScreen from "../screens/WelcomeScreen";
import PhoneContacts from "../screens/PhoneContacts";
import { SimpleLineIcons } from "#expo/vector-icons";
import LoginScreen from "../containers/LoginScreen";
const InviteNavigator = StackNavigator({
DeathMessage: { screen: Message },
PhoneContacts: { screen: PhoneContacts }
});
export const SignedIn = TabNavigator({
Tasks: {
screen: Tasks,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="list" size={30} />
}
},
Home: {
screen: Home,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="home" size={30} />
}
},
Message: {
screen: InviteNavigator,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="envelope-letter" size={30} />
}
},
Profile: {
screen: Profile,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="user" size={30} />
}
}
});
export const SignedOut = StackNavigator({
SignIn: {
screen: LoginScreen,
navigationOptions: {
title: "Sign In"
}
}
});
LoginScreen looks like:
import { connect } from "react-redux";
import React, { Component } from "react";
import {
Button,
View,
Text,
ActivityIndicator,
Alert,
FlatList
} from "react-native";
import { NavigationActions } from "react-navigation";
import { SocialIcon, Card } from "react-native-elements";
import Reactotron from "reactotron-react-native";
import { AsyncStorage } from "react-native";
import { logIn } from "../actions";
import { signIn } from "../components/Auth";
class SignIn extends Component {
async handleClick() {
res = await signIn();
if (res.type == "success") {
expires = String(res.expires);
AsyncStorage.setItem("fbToken", res.token);
AsyncStorage.setItem("expires", expires);
this.props.logIn(res.token, expires);
} else {
console.log("Login Failed");
}
}
render() {
return (
<View style={{ paddingVertical: 20 }}>
<Card title="finis Requires A Facebook Account To Operate">
<SocialIcon
title="Fred"
button
type="facebook"
onPress={() => this.handleClick()}
/>
</Card>
</View>
);
}
}
const mapDispatchToProps = dispatch => {
return {
logIn: fbToken => {
dispatch(logIn(fbToken, expires));
}
};
};
LoginScreen = connect(null, mapDispatchToProps)(SignIn);
export default LoginScreen;
Any help would be greatly appreciated. Happy to completely redesign if pointed in the right direction.

Sorted by adding an auth.checking prop and rendering an activity spinner until it has checked.
render() {
if (this.props.auth.checking == true) {
return (
<ActivityIndicator
animating={true}
style={styles.activityIndicator}
size="large"
/>
);
} else if (this.props.auth.signedIn == true) {
return <SignedIn />;
} else {
return <SignedOut />;
}
}

Related

'TypeError: Cannot read property 'state' of undefined' error' in react-native

I have created the header using defaultNavigationOptions The navigation bar contains Home, signup, login, create blog options. If the user has signed in then Login option should not be visible, instead, logout option should be enabled. I'm using AsyncStorage to store the token.
App.js:
import React from 'react';
import { CreateBlog } from './app/views/CreateBlog.js';
import { BlogDetails } from './app/views/BlogDetails.js';
import { EditBlog } from './app/views/EditBlog.js';
import { DeleteBlog } from './app/views/DeleteBlog.js';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { Home } from './app/views/Home.js';
import { Login } from './app/views/Login.js';
import {
StyleSheet, Text, View, TextInput, TouchableHighlight, Alert, AsyncStorage
} from 'react-native';
import { Signup } from './app/views/Signup.js';
const AppNavigator = createStackNavigator(
{
CreateBlogRT: {
screen: CreateBlog
},
BlogDetailsRT: {
screen: BlogDetails
},
EditBlogRT: {
screen: EditBlog
},
DeleteBlogRT: {
screen: DeleteBlog
},
SignupRT: {
screen: Signup
},
LoginRT: {
screen: Login
},
HomeRT: {
screen: Home,
},
},
{
initialRouteName: 'HomeRT',
defaultNavigationOptions: ({ navigation }) => ({
header: <View style={{
flexDirection: "row",
height: 80,
backgroundColor: '#f4511e', fontWeight: 'bold'
}} >
<TouchableHighlight onPress={() => navigation.navigate('SignupRT')}>
<Text > SignUp</Text>
</TouchableHighlight>
<TouchableHighlight onPress={() => navigation.navigate('CreateChapterRT')}>
<Text > CreateChapter</Text>
</TouchableHighlight>
<TouchableHighlight onPress={() => navigation.navigate('LoginRT')}>
<Text > Login</Text>
</TouchableHighlight>
//getting 'TypeError: Cannot read property 'state' of undefined'
{this.state.logged_in &&
<TouchableHighlight onPress={async () => {
await AsyncStorage.removeItem('token');
await AsyncStorage.removeItem('user_id');
}}>
<Text > Logout</Text>
</TouchableHighlight>
}
</View >
}),
},
}
);
const MyRoutes = createAppContainer(AppNavigator);
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { logged_in: false };
}
componentDidMount = async () => {
var logged_in = await AsyncStorage.getItem('token')
this.setState({ logged_in: false })
}
render() {
return (
<MyRoutes />
);
}
}
Now on clicking the logout button, it deletes the token. I want the logout button should be visible only if the user has logged in. In the same way login & signup options as well. (
const loggedin=AsyncStorage.getItem('token');if(userloggedin)
{showlogout:true;showlogin:false;showSignup:false}.
I don't know where to write the code. Thanks in advance.
after sign-in user you can set userloggedin true
AsyncStorage.setItem('userloggedin',JSON.stringfy(true)
or
AsyncStorage.setItem('userloggedin',Boolean(true))
then getItem
const logged-in = AsyncStorage.getItem('userloggedin')
if(loggedin){
showlogout=true
showlogin=false
showSignup=false
or if your are using state
this.setState({
showlogout:true,
showlogin:false,
showSignup:false})
}.
you can use react life-cycle for this work and also use global variable or state , like this
check this image
https://camo.githubusercontent.com/3beddc08b0e4b44fbdcef20809484f9044e091a2/68747470733a2f2f63646e2d696d616765732d312e6d656469756d2e636f6d2f6d61782f323430302f312a736e2d66746f7770305f565652626555414645434d412e706e67
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {logged_in: false};
}
componentDidMount=async() {
var logged_in = await AsyncStorage.getItem('token')
this.setState({logged_in: false})
}
render() {
const {logged_in} = this.state
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {logged_in}.</h2>
</div>
);
}
}

Login component react-native

I am making a react-native application.
I am trying to find out how can I show or hide the login component on the basis of a token stored. If the token is present in the storage, it would skip the login screen to the dashboard.
Else it will show login screen.
Here is the code to the app.
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, AsyncStorage } from 'react-native';
import Login from './components/Login';
import Dashboard from './components/Dashboard';
export default function App() {
var [ token, setToken ] = useState('');
function loginHandler(recievedToken) {
setToken(recievedToken);
}
async function _readData() {
try {
const value = await AsyncStorage.getItem('Token');
console.log(value);
if (value !== null) {
// We have data!!
loginHandler(value)
} else {
loginHandler(null);
}
} catch (error) {
// Error retrieving data
}
};
return (
<View>
<Login getToken={_readData()} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
You can put conditional statement in your code.
Try this code out.
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, AsyncStorage, ActivityIndictor } from 'react-native';
import Login from './components/Login';
import Dashboard from './components/Dashboard';
export default function App() {
var [ token, setToken ] = useState('');
var [ loading, setLoading ] = useState(true);
function loginHandler(recievedToken) {
setToken(recievedToken);
setLoading(false);
}
async function _readData() {
try {
const value = await AsyncStorage.getItem('Token');
console.log(value);
if (value !== null) {
// We have data!!
loginHandler(value)
} else {
loginHandler(null);
}
} catch (error) {
// Error retrieving data
}
};
if( loading ) {
<ActivityIndictor/>
}
if(token == null){
return (
<View>
<Login getToken={_readData()} />
</View>
);
} else {
return (
<View>
<Dashboard />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Let me know if some error or correction.
Here AuthStack is Login Screen and BottomNavigation is DashBoard.
import React, { useEffect, useState } from "react";
import { NavigationContainer } from "#react-navigation/native";
import AuthStackScreen from "./routes/AuthStack";
import BottomNavigation from "./routes/BottomNavigator";
import firebase from "./config/firebase";
export default App = () => {
const [isLogin, setIsLogin] = useState(false);
const checkLoginIn = () => {
firebase.auth().onAuthStateChanged(user => {
if (user) {
setIsLogin(true);
} else {
setIsLogin(false);
}
});
};
useEffect(() => {
checkLoginIn();
}, []);
return (
<NavigationContainer>
{isLogin ? <BottomNavigation /> : <AuthStackScreen />}
</NavigationContainer>
);
};
In my case
I just used initialRouteName
import React, {Component} from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createNativeStackNavigator} from '#react-navigation/native-stack';
import AsyncStorage from '#react-native-async-storage/async-storage';
import Home from './components/Home';
import Login from './components/Login';
const Stack = createNativeStackNavigator();
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
routeName: 'Login',
};
}
async componentDidMount() {
const token = JSON.parse(await AsyncStorage.getItem('token'));
if (token !== null) {
this.setState({
routeName: 'Bluetooth',
});
}
SplashScreen.hide();
}
render() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName={this.state.routeName}
screenOptions={{
headerShown: false,
}}>
<>
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Home" component={Home} />
</>
</Stack.Navigator>
</NavigationContainer>
);
}
}

this.props.navigation.toggedrawer is not a function-React Native 0.59.9 React Navigation 3.11.0

I have a requirement of using Redux in Tabnavigator which is inside of
an DrawerNavigator.Redux Portion is working fine, But I am unable to
open the drawer on click of a button but the drawer is visible on
swipe gesture.
I am providing my code:-
App.js:-
import * as React from 'react';
import {createAppContainer,createStackNavigator,createBottomTabNavigator} from 'react-navigation';
import RegisterStack from './routes/Register.route';
import SplashStack from './routes/Splash.route';
import Test from './src/pages/Test';
const AppNavigator = createStackNavigator(
{
Splash: SplashStack,
Register: RegisterStack,
StartTest :Test
},
{
initialRouteName: 'StartTest',
headerMode:'none'
});
let Navigation = createAppContainer(AppNavigator);
export default class App extends React.Component {
render() {
return (
<Navigation />
);
}
}
code in Test.js:-
import React from 'react';
import { View,StyleSheet,Text,SafeAreaView,Dimensions,Button } from 'react-native';
import {createAppContainer,createMaterialTopTabNavigator,createDrawerNavigator, DrawerActions} from 'react-navigation';
import ReferenceStack from './Reference';
import QuestionStack from './Question';
import { Provider, connect } from 'react-redux';
import { createStore, combineReducers } from 'redux';
function counter(state, action) {
if (typeof state === 'undefined') {
return 0;
}
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
let store = createStore(combineReducers({ count: counter }));
class DrawerLayout extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<SafeAreaView style={styles.container}>
<Text>{this.props.count}</Text>
<Button
title="Increment"
onPress={() => this.props.dispatch({ type: 'INCREMENT' })}
/>
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
container: {
flex:1,
backgroundColor: "red",
}
});
let CounterContainer = connect(state => ({ count: state.count }))(ReferenceStack);
let StaticCounterContainer = connect(state => ({ count: state.count }))(QuestionStack);
let StaticCounterContainerDrawer = connect(state => ({ count: state.count }))(DrawerLayout);
const DrawerStack = createDrawerNavigator({
Test: {
screen: createMaterialTopTabNavigator({
Reference: {
screen: CounterContainer
},
Question:{
screen: StaticCounterContainer
}
},{
tabBarPosition: 'bottom',
tabBarOptions:{
activeTintColor:'#d61822',
inactiveTintColor:'#5e5e5e',
pressColor:'#d61822'
}
})
}
},{
drawerPosition: "left",
drawerWidth: Dimensions.get('screen').width*.80,
contentComponent: StaticCounterContainerDrawer
});
let DrawerTabNavigation = createAppContainer(DrawerStack);
class Test extends React.Component {
constructor(props) {
super(props);
console.log(props)
}
render() {
return (
<View style={{flex:1}}>
<View style={{height:50,backgroundColor:'yellow'}}></View>
<Provider store={store}>
<DrawerTabNavigation/>
</Provider>
<View style={{height:50,backgroundColor:'yellow'}}>
<Button
title="Open Drawer"
onPress={() => this.props.navigation.toggleDrawer()}
/>
</View>
</View>
);
}
}
export default Test;
When ever Open Drawer button is pressed
_this3.props.navigation.toggedrawer is not a function this error is showing.
I am providing the screen and the error also:-
Please hekp me to open the drawer on click of a button. Thanks in
advance
this.props.navigation.toggedrawer will work only for the screens which are in DrawerNavigator.
May be try this.
import { DrawerActions } from "react-navigation";
this.props.navigation.dispatch(DrawerActions.toggleDrawer())

React-native switch navigation the component for route must be a React component

I'm building an app in react-native. I'm trying to set initial route name dynamically in my navigation with switchNavigator. Here is my code :
Navigation.js
import { createStackNavigator, createAppContainer, createSwitchNavigator } from 'react-navigation'
import homeDisconnect from '../screens/homeDisconnect.js'
import Login from '../screens/Login'
import Register from '../screens/Register'
import Home from '../screens/Home'
import AuthLoading from '../screens/AuthLoading'
const AppStack = createStackNavigator(
{
Home: {
screen: Home,
navigationOptions: {
headerTitle: 'Accueil',
headerLeft: null,
gesturesEnabled: false
}
}
}
)
const AuthStack = createStackNavigator(
{
homeDisconnect: {
screen: homeDisconnect,
navigationOptions: {
headerTitle: null,
headerLeft: null,
header: null
}
},
Login: {
screen: Login,
navigationOptions: {
headerTitle: 'S\'identifier',
headerLeft: null
}
},
Register: {
screen: Register,
navigationOptions: {
headerTitle: 'S\'inscrire'
}
}
},
{
headerLayoutPreset: 'center',
initialRouteName: 'homeDisconnect'
}
)
export default createAppContainer(createSwitchNavigator(
{
AuthLoading: AuthLoading,
AppStack: AppStack,
AuthStack: AuthStack,
}
));
AuthLoading.js
import React, { Component } from 'react'
import {ActivityIndicator, StatusBar, StyleSheet, View} from 'react-native'
import {AppStack, AuthStack} from '../navigation/StackNavigation'
import { connect } from 'react-redux'
class AuthLoading extends Component {
constructor() {
super();
}
componentDidMount(){
this._bootstrapAsync()
}
_bootstrapAsync = async () => {
console.log(this.props)
const userToken = this.props.token
this.props.navigation.navigate(userToken ? 'App' : 'Auth');
};
render() {
return (
<View style={styles.container}>
<ActivityIndicator />
<StatusBar barStyle="default" />
</View>
);
}
}
const mapStateToProps = (state) => {
return state
}
export default connect(mapStateToProps)(AuthLoading);
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
App.js
import {AuthLoading} from './src/screens/AuthLoading'
export default class App extends Component {
render() {
return (
<View>
<AuthLoading></AuthLoading>
</View>
)
}
}
--> import {AppStack, AuthStack} from '../navigation/StackNavigation', is it not possible to do that, that way ? I'm getting that error :
The component for route 'AuthLoading' must be a React component.
What am I doing wrong ?
SwitchNavigator knows to navigate between screen/stack in the same SwitchNavigator, so i recommended to navigate in this way:
userToken ?
this.props.navigation.navigate('AppStack') : this.props.navigation.navigate('AuthLoading')
and you don't need this import so remove it:
import {AppStack, AuthStack} from '../navigation/StackNavigation'
Navigation.js:
export default MainNavigator = createSwitchNavigator(
{
AuthLoading: AuthLoading,
AppStack: AppStack,
AuthStack: AuthStack,
}
});
Now change your code in App.js :
import MainNavigator from './src/screens/AuthLoading'
export default class App extends Component {
render() {
return (
<View>
<MainNavigator />
</View>
)
}
}

How to get previous route in react navigation?

I am user react navigation in react native application. After login I navigate to Home screen from where I want to sign out I should be navigate to previous screen(say Login). But inside navigation props I am unable to find any way to Login screen back without use of goBack function. My navigation is little messy please see my navigation carefuly.
This is my Navigators
import React from 'react';
import{ View, Text } from 'react-native';
// Navigators
import { DrawerNavigator, StackNavigator, TabNavigator } from 'react-navigation'
// Drawer Screens
import Welcome from '../../screens/Welcome';
import Profile from '../../screens/Profile';
// Tab Screens
import Home from '../../screens/Home';
import Message from '../../screens/Message';
//TabNav
const routeConfigs = {
Home: {
screen: Home,
navigationOptions: {
title: 'Home'
}
},
Message: {
screen: Message,
},
}
const tabNavigatorConfig = {
// tabBarComponent: tabBarComponent,
tabBarPosition: 'top',
lazy: true,
tabBarOptions: {
activeTintColor: 'yellow',
inactiveTintColor: 'gray',
style: {
backgroundColor: '#8e24aa',
},
activeBackgroundColor: 'green',
},
header: 'screen'
}
export const TabNav = TabNavigator(routeConfigs, tabNavigatorConfig);
//Used Stack to get Header above TabBar
export const StackNav = StackNavigator({TabNav: { screen: TabNav }});
//DrawerNav
export const DrawerNav = DrawerNavigator (
{
Welcome: { screen: Welcome},
Profile: { screen: Profile },
StackNav: { screen: StackNav}, // Stack Navigator to get Header on each Tabs
},
{
initialRouteName: 'Welcome',
drawerBackgroundColor: '#98eef3',
}
);
This is Welcome or say Login Screen
import React, { Component } from 'react';
import { View, Text, StyleSheet, Button, TouchableOpacity, Modal, BackHandler, Alert, Image } from 'react-native';
import { connect } from 'react-redux';
import firebase from 'firebase';
import {
loginUser
} from '../actions';
import Input from '../components/Input';
import Spinner from '../components/Spinner';
class Welcome extends Component {
constructor(props){
super(props);
this.state = {
modalVisible: false,
email: '',
password: '',
}
this.renderHome = this.renderHome.bind(this);
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
handleBackButton = () => {
Alert.alert(
'Exit App',
'Exiting the application?',
[
{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
{text: 'OK', onPress: () => BackHandler.exitApp()}
],
{ cancelable: false }
)
return true;
}
static navigationOptions = () => ({
drawerLockMode: 'locked-closed'
})
loginButtonPress() {
this.props.loginUser(this.state.email, this.state.password);
}
renderHome(){
this.props.navigation.navigate('StackNav');
}
renderLoginButton(loading){
if(loading){
return <Spinner />;
}else{
return (
<View style={{alignItems: 'center'}}>
<TouchableOpacity style={styles.button} onPress={this.loginButtonPress.bind(this)} >
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
</View>
);
}
}
render() {
return (
<View style={styles.container}>
{(this.props.user)?this.renderHome():null}
<View style={{flex: 3, justifyContent: 'center'}}>
<Input
placeholder="Email"
keyboardType="email-address"
value={this.state.email}
onChangeText={(email) => this.setState({email})}
/>
<Input
placeholder="Password"
value={this.state.password}
onChangeText={(password) => this.setState({password})}
secureTextEntry
/>
{this.renderLoginButton(this.props.loading)}
);
}
}
mapStateToProp = ({auth}) => {
return {
user: auth.user,
error: auth.error,
loading: auth.loading,
}
}
export default connect(mapStateToProp, { loginUser })(Welcome);
This is Home screen
import React, { Component } from 'react';
import { View, Text, Button, Alert, Animated, BackHandler } from 'react-native';
import { connect } from 'react-redux';
import Header from '../components/Header';
import Ionicons from 'react-native-vector-icons/Ionicons';
export class Home extends Component {
constructor(props){
super(props);
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
handleBackButton = () => {
Alert.alert(
'Exit App',
'Exiting the application?',
[
{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
{text: 'OK', onPress: () => BackHandler.exitApp()}
],
{ cancelable: false }
)
return true;
}
static navigationOptions = ({navigation}) =>( {
title: 'Home',
header: <Header headerTitle={navigation.state.routeName}/>,
headerTintColor: '#fff',
});
render(){
console.log(this.props.user) // after signout getting undefined
return (
<View
style={{height: 1000}}
>
<View style={{height: 1000}}>
<Text>Home</Text>
</View>
</View>
);
}
}
mapStateToProp = ({auth}) => {
return {
user: auth.user,
}
}
export default connect(mapStateToProp, null)(Home);
Signout is correctly working but need to navigate back to welcome/login screen.
Instead of using goBack you can try Navigation.reset
import { NavigationActions } from "react-navigation";
...
export const logOut = navigation => {
NavigationActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "Welcome" })]
})
}
use a switch navigator - it is a screen that checks the users current status and forwards them to the appropriate screen.
If user logs in, show user the Home screen
If user logs out show user the Welcome screen
If user arrives unauthenticated show user Welcome screen
update initialRouteName in the in your nav file and added AuthLoadingScreen.
import React from 'react';
import{ View, Text } from 'react-native';
// Navigators
import { DrawerNavigator, StackNavigator, TabNavigator } from 'react-navigation'
// Drawer Screens
import Welcome from '../../screens/Welcome';
import Profile from '../../screens/Profile';
// Tab Screens
import Home from '../../screens/Home';
import Message from '../../screens/Message';
import AuthLoadingScreen from '../../AuthLoading';
//TabNav
const routeConfigs = {
Home: {
screen: Home,
navigationOptions: {
title: 'Home'
}
},
Message: {
screen: Message,
},
}
const tabNavigatorConfig = {
// tabBarComponent: tabBarComponent,
tabBarPosition: 'top',
lazy: true,
tabBarOptions: {
activeTintColor: 'yellow',
inactiveTintColor: 'gray',
style: {
backgroundColor: '#8e24aa',
},
activeBackgroundColor: 'green',
},
header: 'screen'
}
export const TabNav = TabNavigator(routeConfigs, tabNavigatorConfig);
//Used Stack to get Header above TabBar
export const StackNav = StackNavigator({TabNav: { screen: TabNav }});
//DrawerNav
export const DrawerNav = DrawerNavigator (
{
Welcome: { screen: Welcome},
Profile: { screen: Profile },
Authloading: {screen: AuthLoadingScreen}
StackNav: { screen: StackNav}, // Stack Navigator to get Header on each Tabs
},
{
initialRouteName: 'AuthLoading',
drawerBackgroundColor: '#98eef3',
}
);
import React, { Component } from 'react';
import PropTypes from "prop-types";
import {
ActivityIndicator,
AsyncStorage,
StatusBar,
StyleSheet,
View,
Text
} from 'react-native';
import { connect } from 'react-redux'
import { withNavigation } from 'react-navigation'
class AuthLoadingScreen extends Component {
static PropTypes = {
navigation: PropTypes.object,
isAuthenticated: PropTypes.bool
}
componentWillMount() {
this._bootstrapAsync();
}
// Fetch the token from storage then navigate to our appropriate place
_bootstrapAsync = () => {
const userToken = this.props.isAuthenticated ? 'Tabs' : 'Onboarding';
// This will switch to the App screen or Auth screen and this loading
// screen will be unmounted and thrown away
this.props.navigation.navigate(userToken);
};
// Render any loading content that you like here
render() {
return (
<View style={styles.container}>
<ActivityIndicator />
<StatusBar barStyle="default" />
<Text>hello</Text>
</View>
);
}
}
const mapStateToProps = state => {
return {
isAuthenticated: state.auth || false,
};
};
export default connect(mapStateToProps)(withNavigation(AuthLoadingScreen));