From 5659a4632b2187c1b481203e66b2a79e6e76ff27 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Mon, 12 Dec 2022 18:05:43 -0500 Subject: [PATCH] ScrollRestoration on RR 6.4 --- packages/remix-react/scroll-restoration.tsx | 146 +++++++------------- 1 file changed, 48 insertions(+), 98 deletions(-) diff --git a/packages/remix-react/scroll-restoration.tsx b/packages/remix-react/scroll-restoration.tsx index 59ce0dd5c91..b14edb6a004 100644 --- a/packages/remix-react/scroll-restoration.tsx +++ b/packages/remix-react/scroll-restoration.tsx @@ -1,19 +1,15 @@ import * as React from "react"; -import { useLocation } from "react-router-dom"; +import type { ScrollRestorationProps as ScrollRestorationPropsRR } from "react-router-dom"; +import { + useLocation, + UNSAFE_useScrollRestoration as useScrollRestoration, +} from "react-router-dom"; -import { useBeforeUnload, useTransition } from "./components"; import type { ScriptProps } from "./components"; +import { useMatches } from "./components"; let STORAGE_KEY = "positions"; - -let positions: { [key: string]: number } = {}; - -if (typeof document !== "undefined") { - let sessionPositions = sessionStorage.getItem(STORAGE_KEY); - if (sessionPositions) { - positions = JSON.parse(sessionPositions); - } -} +let hydrated = false; /** * This component will emulate the browser's scroll restoration on location @@ -21,29 +17,46 @@ if (typeof document !== "undefined") { * * @see https://remix.run/api/remix#scrollrestoration */ -export function ScrollRestoration(props: ScriptProps) { - useScrollRestoration(); - - // wait for the browser to restore it on its own - React.useEffect(() => { - window.history.scrollRestoration = "manual"; - }, []); - - // let the browser restore on it's own for refresh - useBeforeUnload( - React.useCallback(() => { - window.history.scrollRestoration = "auto"; - }, []) +export function ScrollRestoration({ + getKey, + ...props +}: ScriptProps & { + getKey: ScrollRestorationPropsRR["getKey"]; +}) { + let location = useLocation(); + let matches = useMatches(); + + useScrollRestoration({ + getKey, + storageKey: STORAGE_KEY, + skip: !hydrated, + }); + + // In order to support `getKey`, we need to compute a "key" here so we can + // hydrate that up so that SSR scroll restoration isn't waiting on React to + // hydrate. *However*, our key on the server is not the same as our key on + // the client! So if the user's getKey implementation returns the SSR + // location key, then let's ignore it and let our inline