-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
Disable automatic scrolling when clicks are used to navigate #252
Comments
This isn't confined to |
Yeah. I want to try and nail down all the places where we're auto-scrolling and shouldn't be, and fix them all at once. |
I think we should confine auto-scrolling to |
Agree. From my experiments in Chrome, it looks like using the forward button preserves scroll state as well. Something we want to support? |
I assumed Forward is also popstate (not sure though, haven't worked with history API directly for a long time). Definitely I'm for supporting Forward restoring. |
I don't mean to be impatient, but we have scheduled a release with react-router Friday next week, and this is currently a breaking issue. Can you please indicate if this will be in the works by Monday? If not, I'm happy to do it myself and submit a PR—just don't want to duplicate the work if someone's already doing it. Thanks! |
@gaearon I'd love it if you could make a PR to fix this. It really shouldn't take too much work. All actions go through the LocationActions module. If I were to fix this myself, I'd probably create a separate Thank you! |
Thanks, I was thinking about it similarly. Will do. |
Hello, I think I have an issue related to this. Let's see... In Firefox, when I scroll the page and I press 'F5' to refresh, I see that the scroll bar is in the same place. However, in Chrome, when i press F5, the scroll bar is on the top BUT when I touched it (or just touch the wheel of my mouse) the scroll bar just jumps into the position it was before refresh. I am assuming that the router is causing that. I also noticed that changing preserveScrollPosition to true or false, doesn't make any difference. |
@Difort This looks more like Chrome trying to restore scrolling position on its own, no? |
Can be, because if I set preserveScrollPosition to true/false, then if I go to another page and go back, works with the expected behavior. So the F5 is a browser stuff... And Firefox is handle it fine for me but not Chrome. Maybe the router could save the srollPosition into sessionStorage in order to restore it even after F5? (could be an optional option). |
@mjackson I have a few questions, can we maybe have a little chat on IRC? |
I'm confused by the docs.
The “will not scroll window up globally” wording is misleading isn't it? Because, when set to All this time I was under impression that this flag does the precise opposite. I though “preserve” means “preserve previous position on that page” and not the apparent “preserve current(?) position” that it means. |
Do I (now) understand correctly that |
Maybe the default is documented wrong. I personally don't want to mess with the scroll position by default until we get it right, but I think it does by default. You can do |
Oh, its super confusing now actually. We need a new name like Originally we only meant to scroll it up. So Now that we actually try to "preserve" the position when using the back/forward buttons, the word "preserve" is completely ambiguous. I hope that makes sense. I'll change the name soon, no time for code today though :( Also, @mjackson, until our scrolling antics are rock solid, I would prefer you have to opt-in to it, rather than opt-out. |
@rpflorence Thanks! I'll chatting with @mjackson now about that, will post later. |
So, had a chat with @gaearon. The highlights are (@gaearon please feel free to add to this):
Now, the only question left in my mind is where to put the Can't we just use a top-level |
We used to only scroll up, so if you didn't want us scrolling up, you wanted to preserve the scroll position. It got confusing once we started getting fancy and preserving the scroll position (just read that a few times, you'll remember).
I would vote for
Exactly where it is now. |
Use case? I'm asking because leaving it where it is now doesn't make sense to me and makes things difficult implementation-wise. |
I like top-level method, as it kinda mirrors React's |
I agree with @gaearon |
Could we make scroll behavior implemented as pluggable strategies? Just like React batching strategy can be injected at runtime. For example, we may have This may also be closer to @rpflorence's “stupid defaults” (as |
@gaearon I like that idea. It's also similar to what we currently do with the |
I like all of this |
@rpflorence You're still in favor of per-Route overriding aren't you? I admit that might be useful e.g. if you have an image gallery on some page, but want other pages to scroll to top. However I'm not sure current code handles per-Route overriding correctly. (Please amend me if I'm wrong.) Say, I have In this case, we want to avoid scrolling to top when switching between gallery images. However, when switching to a gallery image the first time after gallery list route, we do want to scroll to top. In other words, per-Route override should only be used when we're transitioning between two routes that are both described by that Route. It may be that router currently works that way but my impression from the code was that it only looks on next route, and not the previous one. My suggestion is following:
Scroll strategy should receive all actions, as well as current and previous route. Does this make sense? |
In other words, in order to properly support route nesting and scroll strategy overrides, when we transition from route A to route B we need to:
I believe this should be enough to cover 90% of use cases and when you want extra flexibility, you can always inject your own strategy. |
Yeah, all in or all out seems better. So either config on Routes or Router.initiateScrollEmulation (or whatever we call it) Sent from my iPhone
|
I'm a bit confused, do you mean you'd rather get rid of Route-specific overrides? I think they can be useful but I'm not sure they're worth the additional complexity. |
Confirm. I don't think route overrides have simple use cases. It depends on the transition. I'd say just have one, non-overridable config. Sent from my iPhone
|
Good. So you agree that we can have a few builtin strategies and if you want to get fancy you can implement your own? What would the API for a strategy be? It should be aware of all transitions, it should also know whether they're initiated by user or browser. It should be able to specify scrollY (which is its primary function). So the "strategy" is an object that can handle location actions (PUSH, POP, etc) and has |
I'd say getScroll that returns {x, y}. Not all apps only scroll vertically. I like the scroll strategy idea a lot. Sent from my iPhone
|
All right.
I have very tight deadlines (need to ship a product rewrite by Friday) so I only have till Tuesday evening to fix this. In case I won't make it, I'll post my work in progress (likely to not include docs), and @mjackson kindly agreed to take over in this case. Please let me know if you have any naming, backward compatibility or API preferences. |
The only thing that bothers me API-wise is that we have different mechanisms (prop vs method) for very similar things (setting location vs scrolling strategy). With scrolling strategy pluggability is a must (so a string prop won't cut it), but with location, you're unlikely to ever need to customize it (and it needs to know about Dispatcher anyway). Are we okay with similar things achieved by different means in API? |
make it happen, we can bike shed later. we're not afraid of api changes right now, the UPGRADE_GUIDE is working great for people. |
OK, that's exactly what I was worried about! No problem then. |
yeah, string for built-in stuff for convenience. On Sun, Sep 28, 2014 at 9:55 AM, Dan Abramov [email protected]
|
I've hacked together a fix! |
This removes support for `preserveScrollPosition` due to its unforunate naming. Instead, we introduce three scrolling strategies: * `none`: Router doesn't scroll the window when routes change * `scrollToTop` (default): Router always scrolls to top when routes change * `imitateBrowser`: Router tries to act like browser acts with server-rendered pages: it scrolls to top when clicking on links, but tries to restore position when navigating back and forward You can only specify these on <Routes />. Per-route overrides are not supported, but you can supply a custom strategy object. This also fixes remix-run#252. Migration path: The default changed from what corresponded to `imitateBrowser`, to `scrollToTop`. If router's server-rendered scrolling imitation worked well for you, you must now specify it explicitly: ``` // before <Routes> <Routes preserveScrollPosition={false}> // after <Routes scrollStrategy='imitateBrowser'> ``` If you wish router to not try to manage scrolling, you must opt out: ``` // before <Routes preserveScrollPosition={true}> // after <Routes scrollStrategy='none'> ``` Also, as a third option, you may now use the simple `scrollToTop` strategy.
Navigation by clicking on a link shouldn't take you back to the last scroll position you were at.
The text was updated successfully, but these errors were encountered: