Skip to content

Commit

Permalink
Change useScrollRestoration to use pagehide event (#9945)
Browse files Browse the repository at this point in the history
Co-authored-by: Sungjin Kim <a01081440011@gmail.com>
  • Loading branch information
brophdawg11 and jakkku authored Jan 24, 2023
1 parent 1787e40 commit db73e94
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/small-squids-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-router-dom": patch
---

Use `pagehide` instead of `beforeunload` for `<ScrollRestoration>`. This has better cross-browser support, specifically on Mobile Safari.
1 change: 1 addition & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,4 @@
- xavier-lc
- xcsnowcity
- yuleicul
- jakkku
26 changes: 24 additions & 2 deletions packages/react-router-dom/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1143,8 +1143,8 @@ function useScrollRestoration({
};
}, []);

// Save positions on unload
useBeforeUnload(
// Save positions on pagehide
usePageHide(
React.useCallback(() => {
if (navigation.state === "idle") {
let key = (getKey ? getKey(location, matches) : null) || location.key;
Expand Down Expand Up @@ -1241,6 +1241,28 @@ export function useBeforeUnload(
}, [callback, capture]);
}

/**
* Setup a callback to be fired on the window's `pagehide` event. This is
* useful for saving some data to `window.localStorage` just before the page
* refreshes. This event is better supported than beforeunload across browsers.
*
* Note: The `callback` argument should be a function created with
* `React.useCallback()`.
*/
function usePageHide(
callback: (event: PageTransitionEvent) => any,
options?: { capture?: boolean }
): void {
let { capture } = options || {};
React.useEffect(() => {
let opts = capture != null ? { capture } : undefined;
window.addEventListener("pagehide", callback, opts);
return () => {
window.removeEventListener("pagehide", callback, opts);
};
}, [callback, capture]);
}

/**
* Wrapper around useBlocker to show a window.confirm prompt to users instead
* of building a custom UI with useBlocker.
Expand Down

0 comments on commit db73e94

Please sign in to comment.