5

I have an app that has what I would call a pretty common navigation pattern upon loading. These are the rules:

  1. When the app opens, navigate to the LoadingPage. Load from storage...
  2. After retrieving information from the store...
    1. If storage.completedOnboarding is false, navigate to OnboardingPage
    2. If storage.completedOnboarding is true, navigate to HomePage
  3. From the OnboardingPage, you can navigate to any of CreateAccountPage, LoginPage, or HomePage. Navigating away from the OnboardingPage sets completedOnboarding to true.

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.

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
  • You might find [this answer](http://stackoverflow.com/a/43227485/6680611) useful. You could initiate the `SET_ONBOARDING_STATUS` action and wait until you receive the `SET_ONBOARDING_STATUS_COMPLETE` before dispatching `NAVIGATE_ACCOUNT_PAGE`. The linked answer should show how that's achievable. – cartant Apr 11 '17 at 06:01
  • Have you found a good solution yet? I have a similar question, so if you have more info please share – Michael Oct 11 '17 at 16:39

0 Answers0