Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NuxtLink - scrollBehavior broken by back navigation #13983

Closed
quadriq opened this issue May 16, 2022 · 12 comments
Closed

NuxtLink - scrollBehavior broken by back navigation #13983

quadriq opened this issue May 16, 2022 · 12 comments

Comments

@quadriq
Copy link

quadriq commented May 16, 2022

Environment


  • Operating System: Linux
  • Node Version: v16.14.2
  • Nuxt Version: 3.0.0-rc.3
  • Package Manager: npm@7.17.0
  • Builder: vite
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Reproduction

https://stackblitz.com/edit/nuxt-starter-xkacmx?file=app/router.options.ts

  • Scroll the main page a little bit.

  • go to "Long Page"

  • go back - the "savedPosition is correct.

  • now go to "Short Page"

  • go back - the home-page scrolled to the top.

Describe the bug

If the page, linked by NuxtLink has shorter content as the original page - by navigation back to original page the router not accepting the savedPosition (the savedPosition showing correctly by console.log(savedPosition) ) . So the original page is then scrolling to the top.

Expected behavior would be that original-page is staying by "savedPosition".

This Router settings where used:

import type { RouterConfig } from '@nuxt/schema';

// https://router.vuejs.org/api/#routeroptions
export default <RouterConfig>{
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      console.log(savedPosition);
      return savedPosition;
    } else {
      return { top: 0, left: 0 };
    }
  },
};

Additional context

here is the proof that this is working with plain vue router - https://stackblitz.com/edit/vue-8fe51f?file=src/router.js
but I am wondering what's then wrong with NuxtLink ?

Logs

No response

@quadriq quadriq changed the title scrollBehavior broken by back navigation NuxtLink - scrollBehavior broken by back navigation May 17, 2022
@gerbenvanlaar
Copy link

gerbenvanlaar commented May 18, 2022

I have the same issue here. Although it persists in rc-3 it was already there in rc-1. I'm using a similar solution but it is kinda glitchy. The scrollBehavior() is called before the route changes causing the page to scroll to the top before it goes to another page, hence the glitchy experience.

@quadriq
Copy link
Author

quadriq commented May 18, 2022

I also noticed that the first page scrolls to top first before going to second one.
Howevere interesting is why the home-page not accepting "savedPosition" if the second page had shorter content as the one from home.
By returning to home-page I see correct data in the console, like {left: 0, top: 300}, but it looks like, it is not taken, like the "short" page resets something in router .

@gerbenvanlaar
Copy link

gerbenvanlaar commented May 18, 2022

Exactly. My best guess is that happens because the scroll position that is passed along to the shorter page is not possible, therefore it goes to the closest top position. That is 0. The scroll becomes 0 again and so do the pages that you visit after too, until you change them again. If that makes sense.

@quadriq
Copy link
Author

quadriq commented May 23, 2022

I played around with this issue. If we set the return position always to top:100

scrollBehavior(to, from, savedPosition) {
      return { top: 100, left: 0 };
    },

In this case we assume that the page allways scrolls to 100 (except the short one ofcourse ). This is working fine with plain vue-3 and vue-router - ( https://stackblitz.com/edit/vue-hbr3jg?file=src%2Frouter.js )

But in Nuxt 3 the short page reset the top position to "0" by accesing the short page. So this "scollBehavior" seems not to play a role in this case at all.

Could it be that displaying of the new page recreates the router taking its current top position?

I also tried to modify the router.mjs of nuxt3 package directly to this:

nuxtApp.vueApp.component("NuxtPage", NuxtPage);
  nuxtApp.vueApp.component("NuxtNestedPage", NuxtPage);
  nuxtApp.vueApp.component("NuxtChild", NuxtPage);
  const baseURL = useRuntimeConfig().app.baseURL;
  const routerHistory = process.client ? createWebHistory() : createMemoryHistory(baseURL);
  const initialURL = process.server ? nuxtApp.ssrContext.url : createCurrentLocation(baseURL, window.location);
  const router = createRouter({
    scrollBehavior(to, from, savedPosition) {
      return { top: 100, left: 0,}
    },
    history: routerHistory,
    routes
  });
  nuxtApp.vueApp.use(router);

  return;

so to pass settings directly to router. The result is the same ....

@minkoonim
Copy link

any news on this?

@quadriq
Copy link
Author

quadriq commented Jul 31, 2022

Is there any chance there would be some work at this issue? It's still the same at RC6. :(
I thinks it's a major bug, because it completely takes dows the user experience for navigation between pages!

@zkulbeda
Copy link

zkulbeda commented Oct 2, 2022

I also feel the bug, it's very annoying. It's still the same at RC11. The scrollBehavior function executes before page render, so, if wait around 50ms by setTimeout, page will has right position. But it isn't solution, because different devices has different render duration, so that we can't use average time. https://stackblitz.com/edit/nuxt-starter-8lhh5x?file=app/router.options.ts

I hope this bug won't be included into release. I agree, it should be a major bug.

@vinksz
Copy link

vinksz commented Oct 3, 2022

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.$router.options.scrollBehavior = () => {
    return { left: 0, top: 0 }
  }
})

Try this?

@minkoonim
Copy link

I think it is all about how much time it takes to
wait for page transition, data fetching, rendering

It would be better
if there is some state or hook
to tell vue-router that
" hey man I'm ready for scroll behavior "
right now it fires way too early

at the moment, I'm using store to save "scrollReady",

  1. when leaving routes, set it false
  2. onMounted and when I'm really ready, set it true.
  3. Inside scrollBehavior function, await till scrollReady to be true.

I'm relly tired of all those "await until(some state).toBe(true)"
and calling scroll-ready

Please, if there is smarter, better way,
I would be so happy to learn...

below is my code

  export default <RouterOptions> {
  async scrollBehavior(to, from, savedPosition) {
    console.log('scroll behavior')
   
    // I set scrollFn in pageMeta for some pages where it should't do any scroll
    const scrollFn = to.meta.scrollFn as Function || function () { return 1 }
    if (scrollFn(to, from) !== 1) {
      console.log('return null due to page meta scroll function')
      return null
    }

    // set delay and default position, 300 is my page transition duration
    const delay = savedPosition
    ? parseInt(to.meta.scrollDelay as string) || 300
    : 0
    const position = savedPosition || { top: 0, left: 0 }

    // if not $pinia just return default top 0 left 0
    const { $pinia } = useNuxtApp()
    if (!$pinia)
      return position

    // wait for pages to call "I'm ready"
    const { scrollReady } = storeToRefs(useBodyStore($pinia))
    await until(scrollReady).toBe(true)

    // wait for delay and return position
    return new Promise((resolve) => {
      setTimeout(() => {
          return resolve(position)
        }, delay)
      })
    },
  }

@danielroe
Copy link
Member

Would you check with the latest edge channel; this may well have been resolved with nuxt/framework#3851.

@zkulbeda
Copy link

@danielroe, yes, it works as expected in edge channel! Waiting for RC13 👀 Thank you
https://stackblitz.com/edit/nuxt-starter-dv9gfi

Copy link
Member

Great. Closing this. If you do encounter a problem with edge, please let me know and I'll happily reopen.

@danielroe danielroe closed this as not planned Won't fix, can't repro, duplicate, stale Oct 27, 2022
@danielroe danielroe added the 3.x label Jan 19, 2023
@danielroe danielroe transferred this issue from nuxt/framework Jan 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants