How can I reset navigation stack for a tab on state change

Hi.

I have an app which has 4 different tabs, each with its own navigation stack. Is there any way I can reset the navigation stack for each tab as I update a bit of state? The state I need to update is done on one tab but it should change what is viewable in the other tabs, which is why I need to reset navigation.

Thanks!

the best way is to have the tab switch the position on the navigation stack, based on the state change. There is no specific command to handle it

Thanks for the comment @aaronksaunders but I don’t understand. Are you saying that after the state change, I should push the tab’s root route onto the navigation history for each tab?

Yes because all of the tabs are already cached in the DOM; so they will update behind the scenes.

How can I push a route on for a specific tab? I tried pushing a route on the navigation history when the state changes but the tab instantly changes when I change state.

For example, tab 1 is where the state should be changed and tab 2 is where the navigation routes should reflect that change. When I update the state on tab 1, I attempt to push a route on the navigation for tab 2 but instead of staying on tab 1, it instantly moves to tab 2, and shows the route I just pushed onto the navigation history. I want to push a route onto the navigation history for tab 2, BUT stay on tab 1

do you have a project in stackblitz I can take a look at?

I just saw this comment… feat: ion-tab-bar add a clear navigation stack option · Issue #21591 · ionic-team/ionic-framework · GitHub

I don’t have a project on stackblitz but here’s a slightly simplified version of my router:

 <IonReactRouter>
        <IonTabs>
          <IonRouterOutlet mode="ios">
            <Route exact path="/dashboard" render={() => <DashboardTab />} />
            <Route exact path="/modules" render={() => <ModulesTab />} />
            <Route exact path="/quizzes" render={() => <QuizzesTab />} />
            <Route exact path="/bulletins" render={() => <BulletinsTab />} />
            <Route exact path="/dashboard/module-:moduleNumber/chapter-content" render={() => <ChapterContent /> } />
            <Route exact path="/modules/module-:moduleNumber" render={() => <ChapterList /> } />
            <Route exact path="/modules/module-:moduleNumber/chapter-content" render={props => <ChapterContent /> } />
            <Route exact path="/quizzes/overview/:moduleNumber" render={() => <QuizOverview />} />
            <Route exact path="/quizzes/overview/:moduleNumber/quiz" render={() => <Quiz />} />
            <Route exact path="/" render={() => <Redirect to="/dashboard" />} />
          </IonRouterOutlet>
          <IonTabBar mode="ios" slot="bottom">
            <IonTabButton tab="dashboard" href="/dashboard">
              <TabHighlight />
              <IonIcon src={"./assets/svgs/Tab_Dashboard_Inactive.svg"} />
              <IonLabel>Dashboard</IonLabel>
            </IonTabButton>
            <IonTabButton tab="modules" href="/modules">
              <TabHighlight />
              <IonIcon icon={"./assets/svgs/Tab_Modules_Inactive.svg"} />
              <IonLabel>Modules</IonLabel>
            </IonTabButton>
            <IonTabButton tab="quizzes" href="/quizzes">
              <TabHighlight />
              <IonIcon icon={"./assets/svgs/Tab_Quiz_Inactive.svg"} />
              <IonLabel>Quizzes</IonLabel>
            </IonTabButton>
            <IonTabButton tab="bulletins" href="/bulletins">
              <TabHighlight />
              <IonIcon icon={"./assets/svgs/Tab_Bulletins_Inactive.svg"} />
              <IonLabel>Bulletins</IonLabel>
            </IonTabButton>
          </IonTabBar>
        </IonTabs>
      </IonReactRouter>

The dashboard route (/dashboard) is where the state is changed and every route within the modules tab (/modules, /modules/module-:moduleNumber, /modules/module-:moduleNumber/chapter-content) should reflect that state change (ideally, just reset to the /modules route).

I tried pushing /modules back onto the navigation history when the state changes but that causes the dashboard to go away. Here’s a snippet of my ChapterList component which is rendered for the /modules/module-:moduleNumber route.

  useIonViewDidEnter(() => {
    const prevValue = bookSelection;
    store.subscribe(() => {
      const s = store.getState().bookSelection; // state is stored in a redux store
      if (prevValue.value !== s.value) {
         // state is changed
         history.push("/modules");
      }
    });
  }, [bookSelection.value]);

Here is the background to my app in case it helps:
My app is a training guide comprised of two books. The “active” book can be changed from the dashboard. The modules tab shows module content for the active book. One book (book A) has 30 modules (numbered 1-30) of content and the other book (book B) has 25 modules (numbered 1-25) of content. The difference in how many modules each book has is important and what causes the app to crash. In the modules tab, you can select a module from the active book that will take you to another page within the modules tab to view all chapters for that module. You can then select a chapter that will take you to yet another page within the modules tab to finally view the chapter content.

Here is my problem:

  • I select book A from the dashboard (the one with 30 modules).
  • I navigate to the modules tab and select module number 28.
  • I navigate back to the dashboard tab and change the app’s state by selecting book B (the one with 25 modules). Book B is now the active book.
  • an exception is thrown because it tries to render a page with module data that doesn’t exist (module 28 doesn’t exist in Book B).

By the way, that link you posted refers to an Angular project but mine is with React. I understand that resetting the navigation goes against the design of how tabs should work but I don’t know what other option I have.

it doesn’t matter if the link I sent is angular or react the UI is the same and basically the Ionic Team is saying that is not the way tabs work so they don’t support it

Got it. Since there’s no way to change the navigation history of one tab from another, I guess I’ll have to rethink the design.