Closed ziv-caspi closed 2 years ago
Try to render conditional routes in the "genRootNavigator" function.
Hey, it's not recommended to add any logic inside gen...Navigator
functions and Navigators
itself (which are located in src/screens/index.ts
), they should be as dumb as possible.
Better way would be to describe AuthNavigator
(for example) in src/screens/index.ts
and toggle AuthNavigator
and RootNavigator
in src/app.tsx
depending on auth state.
// src/screens/index.ts
export const AuthNavigator = (): JSX.Element =>
genStackNavigator([screens.Login, screens.Registration, screens.ForgotPassword]);
// src/app.tsx
export const AppNavigator = observer(() => {
useColorScheme();
const {nav} = useServices();
const {auth} = useStores();
return (
<>
<StatusBar barStyle={getThemeStatusBarStyle()} backgroundColor={getThemeStatusBarBGColor()} />
<NavigationContainer
ref={nav.n}
onReady={nav.onReady}
onStateChange={nav.onStateChange}
theme={getNavigationTheme()}
>
{!!auth.currentUser ? <RootNavigator /> : <AuthNavigator />}
</NavigationContainer>
</>
);
});
Or there is also the other way - you can describe AuthNavigator
as above and just show it as a modal without messing toggling navigators.
Whatever works better for you.
@kanzitelli after the successful login, how can I redirect to a screen in the RootNavigator?
hey @nykolaslima! Could you elaborate more on your use case? I have a possible solution in mind but maybe yours is something different.
Thanks for the fast response @kanzitelli !
I'm pretty new to react/react native, so maybe it's quite simple to solve.
I've implemented your suggested solution and after the successful login I'm trying to redirect to the Main
screen:
const loginResponse: SuccessfulLoginResponse = data?.loginUser;
const token: string = loginResponse.token;
const refreshToken: string = loginResponse.refreshToken;
const user: User = loginResponse.user;
auth.setLoggedUser(user, token, refreshToken);
nav.push('Main');
And I get the following error:
The action 'PUSH' with payload {"name":"Main"} was not handled by any navigator.
Do you have a screen named 'Main'?
If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.
The navigators were configured this way:
const TabNavigator = () => genTabNavigator([tabs.Main, tabs.WIP, tabs.Settings]);
export const AuthNavigator = (): JSX.Element => genStackNavigator([screens.Login]);
// Root Navigator
export const RootNavigator = (): JSX.Element =>
genRootNavigator(TabNavigator, [modals.ExampleModal]);
<>
<StatusBar barStyle={getThemeStatusBarStyle()} backgroundColor={getThemeStatusBarBGColor()}/>
<NavigationContainer
ref={nav.n}
onReady={nav.onReady}
onStateChange={nav.onStateChange}
theme={getNavigationTheme()}
>
{!!auth.currentUser ? <RootNavigator /> : <AuthNavigator />}
</NavigationContainer>
</>
What am I missing here?
@nykolaslima no problem! I just like checking GitHub on Sunday night 😁
So from what I can see, you don't need to do nav.push('Main')
because <RootNavigator />
will automatically show tabs.Main
navigator as it is the first element of the tabs array in TabNavigator
.
Make sure that you set auth.currentUser
in your auth.setLoggedUser(...)
method.
Let me know how it goes!
I tried this and if the app is reloaded (closing it and opening again) then the RootNavigator is shown with the expected tabs. But after clicking into the login button and setting the auth.currentUser
the screen is not "reloaded" with the RootNavigator
@nykolaslima is your AppNavigator wrapped with mobx’s observer(…) function?
mobx’s observer
It worked with the observer in the AppNavigator:
export const AppNavigator = observer((): JSX.Element => {
useColorScheme();
const {nav} = useServices();
const {auth} = useStores();
return (
<>
<StatusBar barStyle={getThemeStatusBarStyle()} backgroundColor={getThemeStatusBarBGColor()}/>
<NavigationContainer
ref={nav.n}
onReady={nav.onReady}
onStateChange={nav.onStateChange}
theme={getNavigationTheme()}
>
{!!auth.currentUser ? <RootNavigator /> : <AuthNavigator />}
</NavigationContainer>
</>
);
});
Thank you very much @kanzitelli :)
@nykolaslima awesome, glad it helped! :)
What is the correct way of implementing a login screen in this template? I have tried storing the logged in user in a store, and using a conditional render in the RootNavigator but I am having errors.