Best solution to prevent recursive links from infinite stacking in history

Hello, I found on the forum many different approaches to solve this problem, but it is not clear what is the best solution for this.

I will put some keywords at the bottom that I was searching for so maybe it can help someone else stuck in the same issue trying to find the solution.

Here is an example problem:

  1. /blog/index/ has link to /blog/post/
  2. /blog/post/ has link back to /blog/index/

After you make the navigation back to /blog/index/ now you have 2 instances of /blog/index/ in history.

If you keep navigating this way (instead of back button), you will end up with infinite history.

For my use case, the ideal solution is to remove the previous duplicate page from history and DOM, but I saw some post by Vladimir (from 2018) which he advised not to do this.

Here is fiddle with simple example: https://jsfiddle.net/j1pukLxo/4/

Thanks for any help!

Keywords:

  • Singleton page
  • Circular links
  • Infinite recursive links
  • Infinite page stacking
  • Recursive page stacking

Проблема решается просто, например в beforeEnter для view удалять запрашиваемый url из истории.

Thank you for the advice shastox. It helped me find the solution.

After really struggling on this all day, I finally found a solution that works.

beforeEnter has one major drawback for my use case, it does not provide direction. It is not always guaranteed you can infer direction from/to URL at least with my structure, so I need to get a page event.

After going through this, I would recommend most people do not try this, changing history can create a lot of bugs. Better to just use reloadCurrent.

If you have different settings for stackPages or reloadPrevious this code may not work. This only works with F7 default config.

I ended up combining 2 different methods to solve it fully

// from routes.js
// this one will fix the case of normal navigation links
// from normal links/navigation

{
  path: '/profile/:userId/',
  component: ProfilePage,
  on: {
    pageMounted(event, page) {
      // only remove duplicate page type from history if
      // its going forward
      if (page.direction !== 'forward') {
        return;
      }

      const history = this.app.views.main.router.history;
      const lastPositionInHistory = history.lastIndexOf(page.route.url);

      this.app.views.main.router.history = history.filter((url, position) => {
        if (url.startsWith('/profile/') && position != lastPositionInHistory) {
          return false;
        }

        return true;
      });
    },
  }
}

But that is not enough, there are also cases where you can jump directly from /profile/1/ to /profile/2/
Without a middle page which will cause the other page to unmount
So for those links you need a wrapper like

// component method

viewProfile(userId) {
  let self = this;
  let app = self.$app;

  const options = {};
  const currentPageIsProfile = app.views.main.router.currentRoute.url.startsWith('/profile/');

  if (currentPageIsProfile) {
    options.reloadCurrent = true;
  }

  app.views.main.router.navigate(`/profile/${userId}/`, options);
}
1 Like

I don’t usually recommend do anything with it, because end up with infinite history is not really a bad thing, and actually many native mobile apps has similar behavior, which is in 99% of cases is totally fine :slight_smile:

So if it annoys you, your solution is also seems fine and ok to me