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

[fix] remove scroll handling code #3835

Closed
wants to merge 1 commit into from
Closed

Conversation

benmccann
Copy link
Member

@benmccann benmccann commented Feb 11, 2022

I started wondering why we need some of the scroll handling stuff and dug into what React Router does. It looks like they have zero scroll handling and rely on the browser to handle it. SvelteKit's scroll handling was originally inspired by Nuxt. I think that older browsers at some point before 2017 didn't have built-in scroll handling with pushState, but have since added it and so there's no longer a reason to include this code

Fixes #3636
Fixes #3621

With this PR, the forward button seems to only scroll to the correct location for every other page. Though given that it fixes two more serious issues, that's probably something we can live with for now

I left disableScrollHandling for now as it wasn't clear to me that we can get rid of it. React Router does not handle deep links by default and you have to include another package for it, but I think it's better that we include it by default

@changeset-bot
Copy link

changeset-bot bot commented Feb 11, 2022

🦋 Changeset detected

Latest commit: 24333aa

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/kit Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify
Copy link

netlify bot commented Feb 11, 2022

✔️ Deploy Preview for kit-demo canceled.

🔨 Explore the source changes: 24333aa

🔍 Inspect the deploy log: https://app.netlify.com/sites/kit-demo/deploys/62070409234d8f0007066705

@Rich-Harris
Copy link
Member

Would this allow us to close #3629 as well?

@PH4NTOMiki
Copy link
Contributor

@Rich-Harris I don't think so, I think it works only for navigating forward/back in history, not for navigating forward with pushState

@Rich-Harris
Copy link
Member

Unfortunately I'm not sure this works? If I take the default template and add a tall div to the index page with a link below it, clicking the link then returning to the index page resets the scroll:

Screen.Recording.2022-02-12.at.9.06.33.AM.mov

What am I missing?

@PH4NTOMiki
Copy link
Contributor

It should work(on few of my vanilla web apps (SPAs) it works, and as @benmccann said, it works on React Router), maybe there is some left over code that sets scrollRestoration
I'll check it out

@benmccann
Copy link
Member Author

Weird. @Rich-Harris, what browser are you testing in?

@Rich-Harris
Copy link
Member

Firefox

@Rich-Harris
Copy link
Member

But I'm seeing the same thing in Chrome

@PH4NTOMiki
Copy link
Contributor

I think I know the reason, it(browser) tries to scrollTo that position before the Kit has the time to render the page completely, and when it fails is stays on the top.

@PH4NTOMiki
Copy link
Contributor

It's possible that it's not possible to kick out the scroll handling code @benmccann

@PH4NTOMiki
Copy link
Contributor

I think I know the reason, it(browser) tries to scrollTo that position before the Kit has the time to render the page completely, and when it fails is stays on the top.

Yeah, I just checked History API docs on Google Developers and this the reason,
and it works on my vanilla web app (and probably React Router too) because when I navigate forward(with pushState) I save previous state(innerHTML only essentially) and when popstate event occurs I just set body.innerHTML to that value, so it's pretty much instant, so the browser can scroll to that position immediately.

@PH4NTOMiki
Copy link
Contributor

@PH4NTOMiki
Copy link
Contributor

But I think that we can actually remove that scroll event listener by using current_history_index
I'll try to fiddle around with it.

@benmccann
Copy link
Member Author

I think I know the reason, it(browser) tries to scrollTo that position before the Kit has the time to render the page completely, and when it fails is stays on the top.

That shouldn't be the case in this PR. The only scrollTo was left basically unchanged from master and happens after a tick() explicitly to ensure the DOM has already been rendered

@PH4NTOMiki
Copy link
Contributor

No @benmccann I mean the internal scrollTo, not ours

@benmccann
Copy link
Member Author

Ah, yeah, I think it's only working if you navigate to a longer page and then hit back, but if you navigate to a shorter page and then it back it won't work. That's why Remix requires you to put the ScrollRestoration component at the bottom of the page. I guess our test suite must not cover that case

But the react-router-hash-link demo somehow does not have this problem and I wonder why...

@Rich-Harris
Copy link
Member

I would guess it's all down to timing. If you're using vanilla React Router then changing routes is basically synchronous. If it's async then the relationship between scroll position and history state is presumably severed. I wonder if delaying pushState until the route has been rendered could affect things

@PH4NTOMiki
Copy link
Contributor

I think it could be, but I'm currently working on removing need for scroll event, l think that's the step in the right direction, if it works, and I think we don't need to do this if that works out, because the scroll event listener is the biggest pain in the current approach.

@benmccann
Copy link
Member Author

I would guess it's all down to timing. If you're using vanilla React Router then changing routes is basically synchronous. If it's async then the relationship between scroll position and history state is presumably severed.

Svelte is synchronous on the server, right? But you're saying it's async on the client? Just curious if there's a reason for that?

I wonder if delaying pushState until the route has been rendered could affect things

I think that's unlikely to help because the pushState seems fine, but it's the restoration of state from the browser that seems to be happening before rendering instead of after like it does in React apparently

@PH4NTOMiki PH4NTOMiki mentioned this pull request Feb 12, 2022
5 tasks
@PH4NTOMiki
Copy link
Contributor

#3873 check this out

@Rich-Harris
Copy link
Member

Svelte is synchronous on the server, right? But you're saying it's async on the client? Just curious if there's a reason for that?

Navigating to a new route involves importing code and fetching data

I think that's unlikely to help because the pushState seems fine

Right, but if pushState isn't tied to rendering then the browser can't link scroll position with history state

@benmccann
Copy link
Member Author

Hmm. Surely people must fetch data when using React Router as well. I assume their router would still work when doing so, but maybe not? It looks like Next does manual scroll restoration behind an experimental flag

@benmccann benmccann closed this Feb 13, 2022
@benmccann benmccann deleted the scroll-handling-2 branch February 13, 2022 04:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants