Skip to content

Instantly share code, notes, and snippets.

@theKashey
Created July 3, 2020 23:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theKashey/e09a5e8d456350e5566502b370dee1c1 to your computer and use it in GitHub Desktop.
Save theKashey/e09a5e8d456350e5566502b370dee1c1 to your computer and use it in GitHub Desktop.
scroll-memory
import React from "react";
import { withRouter } from "react-router-dom";
import { getPageScroll, scrollTo } from "./utils";
const ScrollContext = React.createContext(new Map());
const getLocationKey = location => `${location.pathname}?${location.search}`;
const ScrollMemory = ({ children, history: _history, location }) => {
const [memory] = React.useState(() => new Map());
const locationKey = getLocationKey(location);
const oldKey = React.useRef(locationKey);
if (oldKey.current !== locationKey) {
// performing a pre-render effect
memory.set(oldKey.current, getPageScroll());
oldKey.current = locationKey;
}
React.useEffect(() => {
const onPop = () => {
const key = getLocationKey(window.location);
if (memory.has(key)) {
scrollTo(memory.get(key));
}
};
window.addEventListener("popstate", onPop);
return () => {
window.removeEventListener("popstate", onPop);
};
}, [memory]);
return <ScrollContext.Provider value={memory}>{children}</ScrollContext.Provider>;
};
const ScrollPageMemory = ({ location, disabled }) => {
const memory = React.useContext(ScrollContext);
// reset scroll on mount
React.useLayoutEffect(
() => {
if (!disabled) {
scrollTo(memory.get(getLocationKey(location)) || 0);
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
return null;
};
export const ReactRouterScrollPage = withRouter(ScrollPageMemory);
export const ReactRouterScrollMemory = withRouter(ScrollMemory);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment