I'm trying to implement a React Native App where if isLoading = true, app shows the splash screen, if isLoading = false and isAuthenticated = false app shows authentication screens, and if isLoading = false and isAuthenticated = true app shows the home screen.
// Splash screen while app loading
if (isLoading) screens = (<><SplashScreen /></>);
// Authentication screens while user not authenticated
else if (!isLoading && !isAuthenticated)
screens = (
<>
<Stack.Screen
name="Register"
component={RegisterScreen}
options={{ animationEnabled: false }}
/>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ animationEnabled: false }}
/>
</>
);
// All other screens while user authenticated and onboarded
else
screens = (
<>
<Stack.Screen name="Home" component={TabNavigator} />
<Stack.Screen name="Product" component={ProductScreen} />
</>
);
Right now I have it so that on startup of the app (in Navigation.js) I set a Timeout after 5 seconds with a callback to setIsAuthenticated(false) and setIsLoading(false) which prompts the app to navigate to the authentication page. Otherwise if the user is authenticated (checked by using onAuthStateChanged) I navigate to the homepage.
useEffect(() => {
const timeout = setTimeout(() => {
setIsAuthenticated(false);
setIsLoading(false);
}, 5000);
setTimer(timeout);
return () => clearTimeout(timer);
}, []);
This works well as long as I get the authentication information within 5 seconds (onAuthStateChanged) as I navigate to the correct page. However, there are some cases where the network is very slow and so the callback of the Timeout is called before the authentication state is updated. In this case since the callback is called, I navigate to the authentication screen first then navigates to the home page as soon as the user has been authenticated.
This doesn't seem like a very robust method and so I was wondering if there was a better way about going about this authentication method?
CodePudding user response:
You can base everything on your onAuthStateChanged listener and state management. Create a state that handles user object in your router file and in the auth state listener set the state of the object based on the initial response from onAuthStateChanged. That way, if the listener returns null (no auth user) you can set the navigator's initial route to login, else go inside the app. In order to achieve the loader you can create another state in the router called isLoading and set it to true from the get go. Once the auth listener returns result, regardless if its null or user object, change the state of isLoading to false. With that state you can return loader view before the navigator is returned. It would like similar to this
const [loading,setLoading] = useState(true)
//here goes the abovementioned logic of setting the loading
if(loading){
return <LoaderComponent/>}
return <Navigator/>
CodePudding user response:
Please change the status when authentication api is successful.
const [isAuthenticated,setIsAuthenticated] = useState(false);
...
useEffect(() => {
authAPiCall.then(() => {
setIsAuthenticated(true);
})
const timeout = setTimeout(() => {
setIsLoading(false);
}, 5000);
setTimer(timeout);
return () => clearTimeout(timer);
}, []);