I have an app that has what I would call a pretty common navigation pattern upon loading. These are the rules:
- When the app opens, navigate to the LoadingPage. Load from
storage
... - After retrieving information from the store...
- If
storage.completedOnboarding
isfalse
, navigate to OnboardingPage - If
storage.completedOnboarding
istrue
, navigate to HomePage
- If
- From the OnboardingPage, you can navigate to any of CreateAccountPage, LoginPage, or HomePage. Navigating away from the OnboardingPage sets
completedOnboarding
totrue
.
Essentially users should only see the OnboardingPage the first time they load the app.
When a user navigates away from the OnboardingPage it should set storage.completedOnboarding = true
. I subscribe to the slice of completedOnboarding
on my store to determine whether the user should navigate to HomePage or OnboardingPage when the app loads.
The issue I'm running into is that when I update the store to navigate to CreateAccountPage or LoginPage this also updates storage.completedOnboarding
to true
after performing the navigation.
In the Onboarding component I have:
// When Home, CreateAccount, or Landing is clicked
completeOnboarding(toScreen) {
this.store.dispatch({type: NAVIGATE_ACCOUNT_PAGE, payload: toScreen});
}
Then in my Effects, I have:
@Effect()
navigateAccountPage$ = this.actions$
.ofType(NAVIGATE_ACCOUNT_PAGE)
.mergeMap(() =>
Observable.of(
{type: SET_ONBOARDING_STATUS, payload: true}
)
);
Essentially I want to update completedOnboarding
at the same time as I navigate to the new page. Once the onboarding status is written to Storage, the SET_ONBOARDING_STATUS_COMPLETE
action is triggered which updates the store. This happens after NAVIGATE_ACCOUNT_PAGE
. Essentially with the above Effect
it will trigger these states:
SET_ONBOARDING_STATUS
NAVIGATE_ACCOUNT_PAGE
SET_ONBOARDING_STATUS_COMPLETE
In order to get around this, I check the page that the user is currently on before navigating them based on the completedOnboarding
slice:
this.store.select('completedOnboarding').subscribe(completedOnboarding => {
if (this.rootPage === LoadingPage) {
this.rootPage = completedOnboarding ? HomePage : OnboardingPage;
} else if (this.rootPage === OnboardingPage && completedOnboarding) {
this.rootPage = HomePage;
}
});
This works, but I would rather not have to do these additional conditional checks. I would like to be able to update the completedOnboarding
state without triggering the check on the Onboarding/Home page in some cases.
Is there any way to do this without additional conditional checks?
Example Plunker -- you can see this by setting completedOnboarding
to false
such as when the page loads for the first time. Then clicking either of the "Go To" buttons at the bottom will update the target navigation page, but you will see that the last run operation is still Completed Onboarding
. We do need to complete onboarding with the user goes to the home/login page, but it should also navigate them to that page, i.e. be the last action performed in that state chain.