So, I've just upgraded an ignite-bowser project to their 5.0 template, which includes React Navigation 5, which requires a change from the legacy recommended method of using a SwitchNavigator to swap between 'Auth' and 'App' StackNavigators, to a new declarative auth flow approach that makes the SwitchNavigator redundant.
FYI, Ignite Bowser projects are essentially React Native template apps backed by
React Native
React Navigation
MobX State Tree
TypeScript
Reactotron
And more!
So this all seems simple enough, but I have not been able to get the actual navigators to switch when using a boolean stored in one of the App stores, and set to true
in an action called within the authentication method.
According to server logs, and Reactotron feed, authentication works fine. Reloading the app afterward does render the App navigator, but the session isn't actually valid since memory was cleared. All of the subsequent requests fail, but the application doesn't switch to the Auth navigator.
Here are the relevant code snippets:
root-navigator.tsx
const RootStack = () => {
const { pbidStore } = useStores()
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
gestureEnabled: true,
stackPresentation: "modal",
}}
>
{pbidStore.isAuthenticated ? (
<Stack.Screen
name="pbidStack"
component={PbidNavigator}
options={{
headerShown: false,
}}
/>
) : (
<Stack.Screen
name="authStack"
component={AuthNavigator}
options={{
headerShown: false,
}}
/>
)}
</Stack.Navigator>
/**
* PbidStore Model
*/
export const PbidStoreModel = types.model("PbidStore").props({
....
isAuthenticated: types.optional(types.boolean, false),
})
.actions(self => ({
setStatus(value?: "idle" | "pending" | "done" | "error") {
self.status = value
},
setAuthToken(token: string) {
self.environment.pbidApi.setAuthToken(token)
},
setAuthenticated(value: boolean) {
self.isAuthenticated = value
},
...
}))
.actions(self => ({
authenticate: flow(function*(email: string, password: string, remember: boolean) {
self.setStatus("pending")
try {
const result = yield self.environment.pbidApi.authenticate(email, password)
if (result.kind === "ok") {
self.setAuthToken(result.token)
self.setStatus("done")
self.setAuthenticated(true)
self.loadUser()
if(remember)
yield self.storeCredentials(email, password)
} else {
self.setStatus("error")
self.setAuthenticated(false)
}
} catch {
self.setStatus("error")
self.setAuthenticated(false)
}
}),
...