I was working on an old app using react navigation version 4 the app contains a register and login in page obviously and then the content of the app.
recently I started remaking the content of the app using react navigation version 5 in order to use the shared element animation and the bottom tab navigator and it was fairly simple.
but I struggled with converting the login part to version 5 since the app structure is somewhat complicated and I am somewhat new to react navigation version 5.
i will leave a figure of the app structure bellow a long with samples of the code used.
App.js :
import { setNavigator } from "./app/navigationRef";const articleListFlow = createStackNavigator({ Main: MainScreen, // screen with diffrent articles categories ResultsShow: ResultShowScreen, // article details screen});const loginFlow = createStackNavigator({ Signup: SignupScreen, Signin: SigninScreen,});loginFlow.navigationOptions = () => { return { headerShown: false, };};articleListFlow.navigationOptions = { title: "News Feed", tabBarIcon: ({ tintColor }) => (<View><Icon style={[{ color: tintColor }]} size={25} name={"ios-cart"} /></View> ), activeColor: "#ffffff", inactiveColor: "#ebaabd", barStyle: { backgroundColor: "#d13560" },};const switchNavigator = createSwitchNavigator({ ResolveAuth: ResolveAuthScreen, MainloginFlow: createSwitchNavigator({ //WelcomeScreen: WeclomeScreen, loginFlow: loginFlow, }), mainFlow: createMaterialBottomTabNavigator( { articleListFlow: articleListFlow, ArticleSave: ArticleSaveScreen, // we dont need this one Account: AccountScreen, }, { activeColor: "#ffffff", inactiveColor: "#bda1f7", barStyle: { backgroundColor: "#6948f4" }, } ),});const App = createAppContainer(switchNavigator);export default () => { return (<AuthProvider><App ref={(navigator) => { setNavigator(navigator); }} /></AuthProvider> );};
NavigationRef.js :
import { NavigationActions } from "react-navigation";let navigator;export const setNavigator = (nav) => { navigator = nav;};export const navigate = (routeName, params) => { navigator.dispatch( NavigationActions.navigate({ routeName, params, }) );};// routename is the name of the routes singin singup accountscreen// params information we want to pass to the screen we want to show
AuthContext.js
import { AsyncStorage } from "react-native";import createDataContext from "./createDataContext";import userAPI from "../api/user";// using navigate to access the navigator and redirect the userimport { navigate } from "../navigationRef";// AUTHENTICATION REDUCERSconst authReducer = (state, action) => { switch (action.type) { case "add_error": { return { ...state, errorMessage: action.payload, }; } case "clear_error_message": { return { ...state, errorMessage: "", }; } case "signin": { return { errorMessage: "", token: action.payload, }; } default: return state; }};// CLEARING ERROR MESSAGES WHEN SWITCHING SIGNIN-SIGNUPconst clearErrorMessage = (dispatch) => () => { dispatch({ type: "clear_error_message" });};// AUTOMATIC SIGNIN ONLY USING TOKENS ON USER DEVICEconst tryLocalSignin = (dispatch) => async () => { const token = await AsyncStorage.getItem("token"); if (token) { // if token exists dispatch({ type: "signin", payload: token }); navigate("Main"); } else { // if token doesnt exist navigate("WelcomeScreen"); }};// SIGNUPconst signup = (dispatch) => async ({ email, password }) => { try { const response = await userAPI.post("/signup", { email, password }); await AsyncStorage.setItem("token", response.data.token); dispatch({ type: "signin", payload: response.data.token }); // making use of the navigate component to access navigation // and redirect the user navigate("Main"); } catch (err) { dispatch({ type: "add_error", payload: "Something went wrong with sign up", }); }};// SIGNINconst signin = (dispatch) => async ({ email, password }) => { try { const response = await userAPI.post("/signin", { email, password }); await AsyncStorage.setItem("token", response.data.token); // using signin since the logic is the same dispatch({ type: "signin", payload: response.data.token }); // making use of the navigate component to access navigation // and redirect the user navigate("Main"); } catch (err) { console.log(err); dispatch({ type: "add_error", payload: "Something went wrong with sign in", }); }};// SIGNOUTconst signout = (dispatch) => async () => { // removing the token makes identification not work again await AsyncStorage.removeItem("token"); dispatch({ type: "signout" }); navigate("loginFlow");};// CREATING CONTEXT AND PROVIDER OBJECTS FOR AUTHENTICATIONexport const { Provider, Context } = createDataContext( authReducer, { signin, signup, signout, clearErrorMessage, tryLocalSignin, }, { token: null, errorMessage: "", });
createDataContext.js
import React, { useReducer } from "react";export default (reducer, actions, defaultValue) => { const Context = React.createContext(); const Provider = ({ children }) => { const [state, dispatch] = useReducer(reducer, defaultValue); const boundActions = {}; for (let action in actions) { // for every action in the actions, call it with dispatch boundActions[action] = actions[action](dispatch); } return (<Context.Provider value={{ state, ...boundActions }}> {children}</Context.Provider> ); }; return { Context, Provider };};
My appologies for the long code and thank you in advance for anyone who can help.