-
Notifications
You must be signed in to change notification settings - Fork 325
Allow scroll restoration to be disabled #1431
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
Changes from 4 commits
ddce7fa
039b728
5a6c694
1f76e93
ae31f91
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| --- | ||
| '@shopify/hydrogen': minor | ||
| --- | ||
|
|
||
| Add `restoreScroll` prop to `Link` and `navigate` to allow the scroll restoration behavior to be disabled. | ||
|
|
||
| By default, when a `<Link>` component is clicked, Hydrogen emulates default browser behavior and attempts to restore the scroll position previously used in the visitor's session. For new pages, this defaults to scrolling to the top of the page. | ||
|
|
||
| However, if you are building a user interface that should fetch a new server components request and update the URL but not modify scroll position, then you can disable scroll restoration using the `restoreScroll` prop: | ||
|
|
||
| ```jsx | ||
| import {Link} from '@shopify/hydrogen'; | ||
| export default function Index({request}) { | ||
| const url = new URL(request.normalizedUrl); | ||
|
|
||
| return ( | ||
| <> | ||
| <p>Current param is: {url.searchParams.get('param')}</p> | ||
| <Link to="/?param=foo" restoreScroll={false}> | ||
| Update param to foo | ||
| </Link> | ||
| </> | ||
| ); | ||
| } | ||
| ``` |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -19,6 +19,33 @@ export default function Index() { | |||||
|
|
||||||
| {% endcodeblock %} | ||||||
|
|
||||||
| ## Scroll restoration | ||||||
|
|
||||||
| By default, when a `<Link>` component is clicked, Hydrogen emulates default browser behavior and attempts to restore the scroll position previously used in the visitor's session. For new pages, this defaults to scrolling to the top of the page. | ||||||
|
|
||||||
| However, if you are building a user interface that should fetch a new server components request and update the URL but not modify scroll position, then you can disable scroll restoration using the `restoreScroll` prop: | ||||||
|
||||||
| However, if you are building a user interface that should fetch a new server components request and update the URL but not modify scroll position, then you can disable scroll restoration using the `restoreScroll` prop: | |
| However, if you want to build a user interface that fetches a new server component's request and updates the URL, but doesn't modify the scroll position, then you can disable scroll restoration using the `restoreScroll` prop: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mcvinci I suggest this instead:
However, if you want to build a user interface that re-renders server components and updates the URL, but doesn't modify the scroll position, then you can disable scroll restoration using the
restoreScrollprop:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it! Thanks, @blittle!
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,7 +33,7 @@ export const BrowserRouter: FC<{ | |
|
|
||
| const history = useMemo(() => pHistory || createBrowserHistory(), [pHistory]); | ||
| const [location, setLocation] = useState(history.location); | ||
| const [locationChanged, setLocationChanged] = useState(false); | ||
| const [scrollNeedsRestoration, setScrollNeedsRestoration] = useState(false); | ||
|
|
||
| const {pending, locationServerProps, setLocationServerProps} = | ||
| useInternalServerProps(); | ||
|
|
@@ -42,12 +42,12 @@ export const BrowserRouter: FC<{ | |
| location, | ||
| pending, | ||
| serverProps: locationServerProps, | ||
| locationChanged, | ||
| onFinishNavigating: () => setLocationChanged(false), | ||
| scrollNeedsRestoration, | ||
| onFinishNavigating: () => setScrollNeedsRestoration(false), | ||
| }); | ||
|
|
||
| useLayoutEffect(() => { | ||
| const unlisten = history.listen(({location: newLocation}) => { | ||
| const unlisten = history.listen(({location: newLocation, action}) => { | ||
| positions[location.key] = window.scrollY; | ||
|
|
||
| setLocationServerProps({ | ||
|
|
@@ -56,14 +56,23 @@ export const BrowserRouter: FC<{ | |
| }); | ||
|
|
||
| setLocation(newLocation); | ||
| setLocationChanged(true); | ||
|
|
||
| const state = (newLocation.state ?? {}) as Record<string, any>; | ||
|
|
||
| /** | ||
| * "pop" navigations, like forward/backward buttons, always restore scroll position | ||
| * regardless of what the original forward navigation intent was. | ||
|
Comment on lines
+63
to
+64
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. til |
||
| */ | ||
| const needsScrollRestoration = action === 'POP' || !!state.restoreScroll; | ||
|
|
||
| setScrollNeedsRestoration(needsScrollRestoration); | ||
| }); | ||
|
|
||
| return () => unlisten(); | ||
| }, [ | ||
| history, | ||
| location, | ||
| setLocationChanged, | ||
| setScrollNeedsRestoration, | ||
| setLocation, | ||
| setLocationServerProps, | ||
| ]); | ||
|
|
@@ -112,13 +121,13 @@ function useScrollRestoration({ | |
| location, | ||
| pending, | ||
| serverProps, | ||
| locationChanged, | ||
| scrollNeedsRestoration, | ||
| onFinishNavigating, | ||
| }: { | ||
| location: Location; | ||
| pending: boolean; | ||
| serverProps: LocationServerProps; | ||
| locationChanged: boolean; | ||
| scrollNeedsRestoration: boolean; | ||
| onFinishNavigating: () => void; | ||
| }) { | ||
| /** | ||
|
|
@@ -141,7 +150,7 @@ function useScrollRestoration({ | |
|
|
||
| useLayoutEffect(() => { | ||
| // The app has just loaded | ||
| if (isFirstLoad || !locationChanged) { | ||
| if (isFirstLoad || !scrollNeedsRestoration) { | ||
| isFirstLoad = false; | ||
| return; | ||
| } | ||
|
|
@@ -190,7 +199,7 @@ function useScrollRestoration({ | |
| pending, | ||
| serverProps.pathname, | ||
| serverProps.search, | ||
| locationChanged, | ||
| scrollNeedsRestoration, | ||
| onFinishNavigating, | ||
| ]); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.