Search code examples
javascriptreact-nativeasync-awaitasyncstorage

How to change initial screen in Route.Js with Async Storage in React Native


I am trying to change the entrance point my application in Router.js to not show the user Onboarding screens second time. Basically I set an async storage value. When the onboarding is finished the value return true. As the async storage functions are async, the return statement in Router.js is not waiting the it to return a value. So I can’t change the initial point of my navigation system.

index.js

AppRegistry.registerComponent(appName, () => Router);

Router.js

function Router() {

let first ="App"
let second ="GetStarted"



  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName={checkFirstUsage().then(data=>data?second:first)} screenOptions={{headerShown: false} }>
        <Stack.Screen name="GetStarted" component={GetStarted} />
        <Stack.Screen name="EnterPoem" component={EnterPoem} />
        <Stack.Screen name="Interest" component={Interested} />
        <Stack.Screen name="Begin" component={Begin} />
        <Stack.Screen name="App" component={App} />
      </Stack.Navigator>
    </NavigationContainer>
    
  );
}

checkFirstUsage

const checkFirstUsage = async () => {
    try {
      const value = await AsyncStorage.getItem('@isAsyncStorageSet')
      if(value === null) {
      
      return true
      }
      else{
        return false;
      }
    } catch(e) {
      console.log(e)
    }
  }

any help is appreciated


Solution

  • I think the best approach when you want to manage separated stack navigators is something like

    index.js

    import React, {useState, useEffect} from 'react';
    import OnBoardingRoutes from './onBoarding.routes';
    import AppRoutes from './app.routes';
    import checkFirstUsage from "./checkFirstUsage/path";
    
    
    const Routes: React.FC = () => {
      const [loading, setLoading] = useState(true)
      const [firstUsage,setFirstUsage] =useState(null);
    
      useEffect(() => {
         async function check() {
              const fU = await checkFirstUsage()
              setFirstUsage(fU)
              setLoading(false)
         }
    
         check()
      },[])
    
      if (loading) return null  // or any better component
    
      return firstUsage ? <OnBoardingRoutes /> : <AppRoutes />;
    };
    
    export default Routes;
    

    And then you have your two stacks navigator, with their respective routes

    onBoarding.routes

    import React from 'react';
    import { createStackNavigator } from '@react-navigation/stack';
    import OnBoardingPage1 from '../pages/OnBoardingPage1';
    import OnBoardingPage2 from '../pages/OnBoardingPage2';
    
    
    const App = createStackNavigator();
    
    const OnBoardingRoutes: React.FC = () => (
      <App.Navigator
        initialRouteName="GetStarted"
        screenOptions={{
          headerShown: false,
        }}
      >
        <App.Screen name="OnBoardingPage1" component={OnBoardingPage1} />
        <App.Screen name="OnBoardingPage2" component={OnBoardingPage2} />
    
      </App.Navigator>
    );
    
    export default OnBoardingRoutes;
    

    and your App routes

    app.routes

        import React from 'react';
        import { createStackNavigator } from '@react-navigation/stack';
        import AppPage1 from '../pages/AppPage1';
        import AppPage2 from '../pages/AppPage2';
    
        
        const App = createStackNavigator();
        
        const AppRoutes: React.FC = () => (
          <App.Navigator
            initialRouteName="App"
            screenOptions={{
              headerShown: false,
            }}
          >
            <App.Screen name="AppPage1" component={AppPage1} />
            <App.Screen name="AppPage2" component={AppPage2} />
    
          </App.Navigator>
        );
        
        export default AppRoutes;
    

    and your Router component will looks like

    import React from "react"
    import Routes from "./index";
    
    
        function Router() {
        
          return (
            <NavigationContainer>
               <Routes/>
            </NavigationContainer>
            
          );
        }
    export default Router;