Rematch for Redux: Struggling to see state on different screens - reactjs

I am new to Rematch for Redux. I am redoing my application using Rematch, but I do not know if I am doing any of this correctly? How/Where do I trigger my reducers and effects (Step 3 in Rematch Docs)? I cannot see my state when I switch between screens. The state seems to be resetting. Could someone please help me? I would greatly appreciate it.
I followed this: https://github.com/rematch/rematch
Here is my code down below:
My application will get bigger, thus the reason why I placed these in different files to build up into the models.js.
store/user.js
const user = {
state: {},
reducers: {
login(payload) { return payload },
email(state, payload) {
return { ...state, payload }
},
password(state, payload) {
return { ...state, payload }
},
username(state, payload) {
return { ...state, payload }
},
fullname(state, payload) {
return { ...state, payload }
},
}
}
export default user
store/index.js
import { init } from '#rematch/core'
import user from './user'
const models = {
user,
}
const store = init({
models,
})
export default store
App.js
import * as React from 'react';
import SwitchNavigator from './navigation/switchNavigator'
import { Provider } from 'react-redux'
import 'redux'
import store from './store/index'
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<SwitchNavigator/>
</Provider>
);
}
}
navigation/switchNavigator
import * as React from 'react';
import TabNavigatorScreen from './tabNavigator'
import AuthNavigatorScreen from './authNavigator'
import { createAppContainer } from 'react-navigation';
import { createSwitchNavigator } from 'react-navigation-switch-transitioner'
const switchNavigator = createSwitchNavigator(
{
Home: {
screen: TabNavigatorScreen
},
Auth: {
screen: AuthNavigatorScreen
}
},
{
initialRouteName: 'Auth',
}
);
export default createAppContainer(switchNavigator);
navigation/authNavigator
import * as React from 'react';
import LoginScreen from '../screens/login'
import SignUpScreen from '../screens/signup'
import MainScreen from '../screens/main'
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
const authNavigator = createStackNavigator(
{
Main: {
screen: MainScreen,
navigationOptions: {
header: null,
}
},
Login: {
screen: LoginScreen,
navigationOptions: {
title: 'Login',
headerTintColor: '#404040',
headerTitleStyle: {
color: '#404040',
},
headerBackTitleStyle: {
color: '#404040',
},
headerBackTitle: null,
}
},
Signup: {
screen: SignUpScreen,
navigationOptions: {
title: 'Sign Up',
headerTintColor: '#404040',
headerTitleStyle: {
color: '#404040',
},
headerBackTitleStyle: {
color: '#404040',
},
headerBackTitle: null,
}
}
},
{
initialRouteName: 'Main',
}
);
export default createAppContainer(authNavigator);
screens/signUp
import * as React from 'react';
import {
TextInput,
Text,
KeyboardAvoidingView,
SafeAreaView,
TouchableOpacity,
Alert,
}
from 'react-native';
import styles from '../styles'
import { connect } from 'react-redux';
import '#expo/vector-icons';
import 'redux';
class Signup extends React.Component {
render() {
const { routeName } = this.props.navigation.state
return (
<SafeAreaView style={styles.container}>
<KeyboardAvoidingView behavior='position'>
<Text style={styles.mainText}>
EMAIL
</Text>
<TextInput
style={styles.inputText}
editable={routeName === 'Signup' ? true : false}
value={this.props.user.email}
onChangeText={input => this.props.email(input)}
/>
<Text style={styles.mainText}>
PASSWORD
</Text>
<TextInput
style={styles.inputText}
editable={routeName === 'Signup' ? true : false}
value={this.props.user.password}
onChangeText={input => this.props.password(input)}
secureTextEntry={true}
/>
<Text style={styles.mainText}>
USERNAME
</Text>
<TextInput
style={styles.inputText}
value={this.props.user.username}
onChangeText={input => this.props.username(input)}
/>
<Text style={styles.mainText}>
FULL NAME
</Text>
<TextInput
style={styles.inputText}
value={this.props.user.fullname}
onChangeText={input => this.props.fullName(input)}
/>
<TouchableOpacity
style={styles.buttonLighGray}
onPress={() => Alert.alert('Sign up')}>
<Text style={styles.buttonDarkText}>
Accept & Sign Up
</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
}
const mapState = (state) => ({
user: state.user,
})
const mapDispatch = ({ user: { email, password, username, fullname }}) => ({
email: () => email(),
password: () => password(),
username: () => username(),
fullname: () => fullname(),
})
export default connect(mapState, mapDispatch)(Signup)
The Login screen is using the same state as Sign up screen.

The state will never change because you don't pass any parameters while dispatching an action.
const mapDispatch = dispatch => ({
setEmail: mail => dispatch.user.email(mail)
})
Everytime you called a function before you just invoked the reducer without a parameter.
Regarding your rematch model. Your reducers should not just return ...state & payload. Try to
const user = {
state: {},
reducers: {
email(state, email) {
return { ...state, email }
},
password(state, password) {
return { ...state, password }
},
username(state, username) {
return { ...state, username }
},
fullname(state, fullname) {
return { ...state, fullname }
},
}
}

Related

How to pass multiple values to react native context API

I'm new to react native concepts. I'm trying to pass functions and a parameter to context API so that I can access those in my child component. I'm trying to implement basic login functionality that will show different messages based on user login status. The functionality works when I pass the SignIn method to my child component but the same function is not accessible when I send it along with some variable. The below code and notes can explain the problem clearly.
In the below code as you can see I'm passing my reducer function and initial states from which I get the error messages and sign function <AuthenticationContext.Provider value={[authContext, initialLoginState]}>
App.js
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import BottomNavigation from './src/Navigations/BottomNavigation';
import AuthStackNavigation from './src/Navigations/AuthStackNavigation'
import { useEffect, useMemo, useReducer } from 'react';
import { View } from 'react-native-animatable';
import apiCaller from "./src/api/apiCaller";
import { ActivityIndicator, Text } from 'react-native';
import { AuthenticationContext } from './src/context/AuthenticationContext'
import { Provider as VideoProvider } from './src/context/videoContext'
import { Context as VideoContext } from './src/context/videoContext'
import AsyncStorage from '#react-native-async-storage/async-storage'
export default function App() {
//Initial state values
const initialLoginState = {
isLoading: true,
userName: null,
userToken: null,
errorMessage: ''
}
//Reducer function
const loginReducer = (prevState, action) => {
switch (action.type) {
case 'LOGIN':
return {
...prevState,
userToken: action.token,
userName: action.id,
isLoading: false
};
case 'LOGOUT':
return {
...prevState,
userName: null,
userToken: null,
isLoading: false,
};
case 'REGISTER':
return {
...prevState,
userToken: action.token,
userName: action.id,
isLoading: false,
};
case 'ERROR':
return {
...prevState,
errorMessage: action.response,
isLoading: false
};
default:
return { userToken: null }
}
}
//Defining useReducer
const [newLoginState, dispatch] = useReducer(loginReducer, initialLoginState);
const authContext = useMemo(() => ({
signIn: async (email, password) => {
try {
const userData = {
email: email,
password: password,
};
const response = await apiCaller.post("/login", userData);
if (response.data.code == '200') {
await AsyncStorage.setItem('userToken', response.data.token)
dispatch({ type: 'LOGIN', id: email, token: response.data.token })
}
else if (response.data.code == '404') {
dispatch({ type: 'ERROR', response: response.data.message })
}
} catch (err) {
console.log(err);
}
}
}), []);
return (
<VideoProvider value={VideoContext}>
<AuthenticationContext.Provider value={{authContext, initialLoginState}}>
<NavigationContainer>
{newLoginState.userToken == null ?
<AuthStackNavigation />
:
<BottomNavigation />
}
</NavigationContainer>
</AuthenticationContext.Provider>
</VideoProvider>
);
}
and in the below file, I'm fetching the provider vales by
const { signIn, initialLoginState } = useContext(AuthenticationContext) but its giving me "signIn is not a function. (In 'signIn(email, password)', 'signIn' is undefined)" error but signIn method is accessible when i just try to pass and access SignIn method alone.
Signinscreen.js
import React, { useState } from 'react'
import { Ionicons, MaterialIcons } from '#expo/vector-icons';
import { Text, View, StyleSheet, TouchableOpacity, Platform, StatusBar } from 'react-native';
import { WindowHeight, WindowWidth } from '../utils/PlatformDimention'
import PrimaryFormInput from "../components/PrimaryFormInput";
import PrimaryFormButton from "../components/PrimaryFormButton";
import { AuthenticationContext } from "../context/AuthenticationContext";
import { useContext } from 'react';
const UserLogin = ({ navigation }) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const { signIn, initialLoginState } = useContext(AuthenticationContext)
const loginHandle = (email, password) => {
signIn(email, password);
}
return (
<View style={styles.container}>
<StatusBar barStyle='light-content' />
<View style={styles.header}>
<View style={{ flex: 1, }}>
<TouchableOpacity onPress={() => navigation.goBack()}>
<MaterialIcons style={styles.goBack} name="arrow-back" size={WindowHeight / 27} />
</TouchableOpacity>
</View>
<View style={{ flex: 2, alignItems: 'center', justifyContent: 'center', }}>
<Ionicons
style={{ color: "#fff" }} name="logo-bitbucket" size={WindowHeight * 10 / 100} />
</View>
<View style={{ flex: 1, alignItems: 'flex-end' }}>
</View>
</View>
<View style={styles.footer}>
<View style={styles.topFlex}></View>
<View style={styles.middleFlex}>
<Text style={styles.loginText}>Welcome!</Text>
<Text style={styles.loginSubTextSub}>Login to your existing account.</Text>
<PrimaryFormInput
inputValue={email}
onChangeText={(userEmail) => setEmail(userEmail)}
inputPlaceHolder='Email'
iconName="user"
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
/>
<PrimaryFormInput
inputValue={password}
onChangeText={(userPassword) => setPassword(userPassword)}
inputPlaceHolder='Password'
iconName="key"
secureTextEntry={true}
/>
<PrimaryFormButton
ButtonText='Login'
onPress={() => loginHandle(email, password)}
/>
</View>
<View style={styles.bottomFlex}></View>
</View>
</View>
)
}
export default UserLogin
Could anyone of you please let me know how to pass both method and parameters to my child component and access it?
Your mistake is just here
const { signIn, initialLoginState } = useContext(AuthenticationContext)
Because you pass the context object like this
<AuthenticationContext.Provider value={{authContext, initialLoginState}}>
You need to do the destructruring like this
const { authContext : { signIn }, initialLoginState } = useContext(AuthenticationContext)

Navigation if not authorized does not work with react-native?

Problem:
I have created a react native application in there I am checking if not authorized I am removing the async storage and redirecting to login. To handle the Axios easily I have created an HTTP client file like this.
import axios from "axios";
import { AsyncStorage } from "react-native";
import { NavigationActions } from 'react-navigation';
// TODO: Replace this with actual JWT token from Keycloak
axios.defaults.headers.post["Content-Type"] = "application/json";
// Create axios instance for api calls
var instance = null;
export const setAuth = async () => {
const token = await AsyncStorage.getItem("jwt");
instance = axios.create({
baseURL: "",
timeout: 150000,
headers: {
Authorization: "Bearer " + token,
"Content-Type": "application/json"
}
});
instance.interceptors.response.use(
function(response) {
return response;
},
async function(error) {
console.log(error);
if (error.response.status) {
if (error.response.status === 401) {
AsyncStorage.removeItem('jwt')
AsyncStorage.removeItem("user");
NavigationActions.navigate({
routeName: 'login'
});
} else {
return error;
}
}
}
);
};
export const Get = (route, data) => {
function getData() {
return instance.get(
route,
data == null ? { data: {} } : { data: JSON.stringify(data) }
);
}
if (instance) return getData();
return setAuth().then(getData);
};
export const Post = (route, data) => {
function postData() {
return instance.post(route, JSON.stringify(data));
}
if (instance) return postData();
return setAuth().then(postData);
};
I am accessing this HTTP client file inside the redux logic function. So this is outside of the component. Problem Now I have faced is It is removing the Asyncstorage but the navigation does not seem to work correctly.
How I create My routes is this.
import React, { Component } from "react";
import { createAppContainer } from "react-navigation";
// import { createStackNavigator } from "react-navigation";
import { createBottomTabNavigator } from "react-navigation-tabs";
import { createStackNavigator } from "react-navigation-stack";
import IonIcon from "react-native-vector-icons/Ionicons";
import { Image } from "react-native";
import LoginScreen from "./components/Login/Login";
import HomeScreen from "./components/Home/Home";
import SettingsScreen from "./components/Settings/Settings";
import FinesScreen from "./components/Fines/Fines"
import ChangePassword from "./components/Changepassword/Changepassword";
const SettingsTab = createStackNavigator(
{
settings: { screen: SettingsScreen },
changePassword: { screen: ChangePassword }
},
{
initialRouteName: "settings",
headerMode: "none"
},
(navigationOptions = {
headerMode: "none"
})
);
const TabNav = createBottomTabNavigator(
{
home: {
screen: HomeScreen,
navigationOptions: {
tabBarLabel: false,
tabBarIcon: () => (
<Image source={require("../assets/invalid-name.png")} />
)
}
},
fines: {
screen: FinesScreen,
navigationOptions: {
tabBarLabel: false,
headerMode: "none",
tabBarIcon: () => (
<Image source={require("../assets/icon-service-fines.jpg")} />
)
}
},
settings: {
screen: SettingsTab,
navigationOptions: {
tabBarLabel: false,
headerMode: "none",
tabBarIcon: () => <Image source={require("../assets/settings.png")} />
}
}
},
{
tabBarPosition: "bottom",
swipeEnabled: true,
animationEnabled: true,
tabBarOptions: {
activeTintColor: "#FFFFFF",
inactiveTintColor: "#F8F8F8",
borderTopColor: "transparent",
style: {
backgroundColor: "#fffff",
borderTopColor: "transparent",
paddingTop: 0
},
indicatorStyle: {
borderBottomColor: "#87B56A",
borderBottomWidth: 2
},
tabStyle: {
justifyContent: "center"
}
}
}
);
const MainNavigator = createStackNavigator(
{
login: { screen: LoginScreen },
tab: { screen: TabNav }
},
{
initialRouteName: "login",
headerMode: "none"
},
(navigationOptions = {
headerMode: "none"
})
);
const AppContainer = createAppContainer(MainNavigator);
export default AppContainer;
An I used it in the app.js file like this.
import React from "react";
// import Login from "./src/components/Login/Login";
// import Register from "./src/components/Register/Register";
import Route from "./src/route";
import { Provider } from "react-redux";
import { createLogicMiddleware } from "redux-logic";
import { createStore, applyMiddleware, compose } from "redux";
import NavigationService from "./src/services/navigationService";
import reducers from "./src/reducers";
import services from "./src/services";
const logicMiddleware = createLogicMiddleware(services, {});
const middleware = applyMiddleware(logicMiddleware);
const composeEnhancers = compose;
const enhancer = composeEnhancers(middleware);
let store = createStore(reducers, enhancer);
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<Route
// ref={navigatorRef => {
// NavigationService.setNavigator(navigatorRef);
// }}
></Route>
</Provider>
);
}
}
Can someone help me to solve this issue? Thank you.
NavigationActions return an object that can be sent to the router using navigation.dispatch() method
You can achieve solution in multiple ways. Here I am going to explaining without Props
First you need to create a service
let _navigator;
function setNavigator(navRef) {
_navigator = navRef;
}
function navigate(navAction) {
_navigator.dispatch(
navAction
);
}
// add other navigation functions that you need and export them
export default {
navigate,
setNavigator,
};
In App container create a ref for
<AppContainer
ref={navigatorRef => {
NavigationService.setNavigator(navigatorRef);
}}
/>
Use in your http client file
import NavigationService from 'path-to-NavigationService.js';
NavigationService.navigate(NavigationActions.navigate({
routeName: 'login'
}););
expo reference

How to reset in react navigation

I'm building a App with a QRCode Scanner and React Navigation. After navigating from the QRScanner to another screen the QRScanner is still active. I found out, that I have to reset my Navigator with StackActions (right?). I tried it with this in my success screen (which comes after the QRScanner):
const resetAction = StackActions.reset({
index: 3,
actions: [NavigationActions.navigate({ routeName: 'VerificationSuccess' })],
});
this.props.navigation.dispatch(resetAction);
But it doesn't work. Unfortunately, I could find any tutorial...
This is my navigator:
import { createStackNavigator } from 'react-navigation';
import VerificationScreen from './VerificationScreen';
import QRScanner from './QRScanner';
import ChatG from '../ChatG';
import VerificationSuccess from './VerificationSuccess';
export default createStackNavigator(
{
VerificationScreen: {
screen: VerificationScreen,
},
QRScanner: {
screen: QRScanner,
},
VerificationSuccess: {
screen: VerificationSuccess,
},
ChatG: {
screen: ChatG,
}
}
);
Could someone please help me?
You may not be familiar with SwitchNavigator yet. The purpose of SwitchNavigator is to only ever show one screen at a time.
Use switchStackNavigator as below:
const AppStack = AppStackNavigator;
const AuthStack = AuthStackNavigator;
export default createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppStack,
Auth: AuthStack
},
{
initialRouteName: "AuthLoading"
}
);
Full working example below,
import React from 'react';
import {
ActivityIndicator,
AsyncStorage,
Button,
StatusBar,
StyleSheet,
View,
} from 'react-native';
import { StackNavigator, SwitchNavigator } from 'react-navigation'; // Version can be specified in package.json
class SignInScreen extends React.Component {
static navigationOptions = {
title: 'Please sign in',
};
render() {
return (
<View style={styles.container}>
<Button title="Sign in!" onPress={this._signInAsync} />
</View>
);
}
_signInAsync = async () => {
await AsyncStorage.setItem('userToken', 'abc');
this.props.navigation.navigate('App');
};
}
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome to the app!',
};
render() {
return (
<View style={styles.container}>
<Button title="Show me more of the app" onPress={this._showMoreApp} />
<Button title="Actually, sign me out :)" onPress={this._signOutAsync} />
</View>
);
}
_showMoreApp = () => {
this.props.navigation.navigate('Other');
};
_signOutAsync = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Auth');
};
}
class OtherScreen extends React.Component {
static navigationOptions = {
title: 'Lots of features here',
};
render() {
return (
<View style={styles.container}>
<Button title="I'm done, sign me out" onPress={this._signOutAsync} />
<StatusBar barStyle="default" />
</View>
);
}
_signOutAsync = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Auth');
};
}
class AuthLoadingScreen extends React.Component {
constructor() {
super();
this._bootstrapAsync();
}
// Fetch the token from storage then navigate to our appropriate place
_bootstrapAsync = async () => {
const userToken = await AsyncStorage.getItem('userToken');
// 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 ? 'App' : 'Auth');
};
// Render any loading content that you like here
render() {
return (
<View style={styles.container}>
<ActivityIndicator />
<StatusBar barStyle="default" />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
const AppStack = StackNavigator({ Home: HomeScreen, Other: OtherScreen });
const AuthStack = StackNavigator({ SignIn: SignInScreen });
export default SwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppStack,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}`enter code here`
);

React navigation broken within function call

I'm new to react native and I can only seem to find documentation for how to navigate between screens in the return() method for react native. I'm wondering what the syntax is for navigation in a function call. The line I am having trouble with is line 37 (in the login function).
import React, {Component} from 'react';
import {
View,
Text,
TouchableHighlight,
TouchableOpacity,
TextInput
} from 'react-native';
import Input from './Input';
import Icon from 'react-native-vector-icons/MaterialIcons';
import {firebaseApp} from './App';
import {Tabs} from './Router';
export default class LoginScreen extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
password: '',
status: ''
}
this.login = this.login.bind(this);
}
login(){
console.log("Logging in");
firebaseApp.auth().signInWithEmailAndPassword(this.state.email, this.state.password).catch(function(error) {
console.log(error.code);
console.log(error.message);
})
this.props.navigation.navigate('TabNav');
console.log("Navigate to Home");
}
render() {
var styles = require('./Styles');
const {navigate} = this.props.navigation;
return(
<View style={styles.loginContainer}>
<Text style={styles.loginHeader}>PRINCETON EVENTS</Text>
<TextInput
style={styles.loginInput}
placeholder="Email"
autoCapitalize='none'
onChangeText={(text) => this.setState({email: text})}
value={this.state.email}
returnKeyType='next'/>
<TextInput
secureTextEntry
style={styles.loginInput} placeholder="Password"
onChangeText={(text) => this.setState({password: text})}
value={this.state.password}
autoCapitalize='none'
returnKeyType='go'/>
<TouchableOpacity style={styles.loginButton}>
<Text style={styles.loginText} onPress={this.login}>LOGIN</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.loginButton}
onPress = {() => navigate('CreateAccount')}>
<Text style={styles.loginText}> CREATE ACCOUNT </Text>
</TouchableOpacity>
</View>
);
}
}
This is Router.js
import React from 'react';
import {StackNavigator, TabNavigator} from 'react-navigation';
import InputScreen from './InputPage';
import HomeScreen from './Home';
import DetailsScreen from './Details';
import MyEventsScreen from './MyEvents';
import EditScreen from './EditPage';
import MapScreen from './Map';
import CreateAccountScreen from './CreateAccount';
import LoginScreen from './Login';
export const MyEventsStack = StackNavigator({
MyEvents: {
screen: MyEventsScreen,
navigationOptions: {
header: null
}
},
MyEventsDetails: {
screen: EditScreen,
navigationOptions: {
header: null,
},
},
});
export const EventsStack = StackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: {
header: null,
},
},
Details: {
screen: DetailsScreen,
navigationOptions: {
header: null,
},
},
});
export const Tabs = TabNavigator({
Home: {screen: EventsStack},
EventMap: {screen: MapScreen},
Input: {screen: InputScreen},
MyEvents:{screen: MyEventsStack},
},{
tabBarOptions: {
activeTintColors: '#e91e63',
}
});
export const LoginNav = StackNavigator({
Login: { screen: LoginScreen,
navigationOptions: {
header: null,
},
},
CreateAccount: { screen: CreateAccountScreen,
navigationOptions: {
header: null,
}
},
});
/*export const SuccessLoginNav = StackNavigator({
Main: { screen: Tabs,
navigationOptions: {
header: null,
}
},
});*/
export const Root = StackNavigator({
TabNav: {
screen: Tabs,
}
}, {headerMode: 'none'});
In login, you're declaring a function but neither invoking it or assigning it to anything:
() => this.props.navigation.navigate('Home');
Essentially that line does nothing. Try removing the anonymous function declaration:
this.props.navigation.navigate('Home');

How to implement a multi step login in react or react native

I would like to implement a multi step login, similar to slack (it first asks the domain name, then the email, and later the password) in react and react-native.
I would like to know what are the best practices to do it?
Should I use a router/navigation solution like ReactNavigation https://github.com/react-community/react-navigation?
That's one way to do it, sure. The way I would do it is a single component:
class LoginComponent extends React.Component {
constructor(props) {
super(props);
this.state = { stage: 0 };
}
onDomainSubmit(data) {
this.props.getDomain(data.domain).then((domain) => {
this.setState({ domain, stage: 1 });
});
}
render() {
const { stage, domain } = this.state;
if (stage === 0) {
return <GetDomainForm onSubmit={ this.onDomainSubmit }... />;
} else if (stage === 1) {
return <LoginToDomainForm domain={ domain }... />;
}
}
}
getDomain is an action creator which has been injected into the component via react-redux's connect - although that's not necessary.
there's less headache that way, and everything you need is contained within one component.
you can use SwitchNavigator.
import React, { Component } from 'react';
import { StackNavigator, TabNavigator, SwitchNavigator } from 'react-navigation';
import AuthLoadingScreen from '../views/users/auth';
import LoginScreen from '../views/users/login';
import RegisterScreen from '../views/users/register';
import ResetPasswordScreen from '../views/users/resetPassword';
import MainTabNavigator from './MainTabNavigator';
export const AuthStack = StackNavigator({
Auth: { screen: AuthLoadingScreen, navigationOptions: { header: null } },
Login: { screen: LoginScreen, navigationOptions: { header: null } },
Register: { screen: RegisterScreen, navigationOptions: { header: null } },
ResetPassword:{ screen: ResetPasswordScreen, navigationOptions: { header: null } }
},{
initialRouteName: "Auth"
});
export const AppStack = TabNavigator(
{ screen: MainTabNavigator, },
{ navigationOptions: {
headerStyle: { backgroundColor: '#f4511e', },
headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold', },
},
}
);
export const createRootNavigator = () => {
return SwitchNavigator(
{
SignedIn: { screen: AuthStack },
SignedOut: { screen: AppStack }
},
{
initialRouteName: "SignedIn"
}
);
};

Resources