Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Last active September 5, 2020 16:46
Show Gist options
  • Save ryanflorence/39a37a85254159fd7a5ca54027e175dc to your computer and use it in GitHub Desktop.
Save ryanflorence/39a37a85254159fd7a5ca54027e175dc to your computer and use it in GitHub Desktop.
import React from "react";
import { Location } from "@reach/router";
let scrollPositions = {};
class ManageScrollImpl extends React.Component {
componentDidMount() {
try {
// session storage will throw for a few reasons
// - user settings
// - in-cognito/private browsing
// - who knows...
let storage = JSON.parse(sessionStorage.getItem("scrollPositions"));
if (storage) {
scrollPositions = JSON.parse(storage) || {};
let { key } = this.props.location;
if (scrollPositions[key]) {
window.scrollTo(0, scrollPositions[key]);
}
}
} catch (e) {}
window.addEventListener("scroll", this.listener);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.listener);
}
componentDidUpdate() {
const { key } = this.props.location;
if (!scrollPositions[key]) {
// never seen this location before
window.scrollTo(0, 0);
} else {
// seen it
window.scrollTo(0, scrollPositions[key]);
}
}
listener = () => {
scrollPositions[this.props.location.key] = window.scrollY;
try {
sessionStorage.setItem(
"scrollPositions",
JSON.stringify(scrollPositions)
);
} catch (e) {}
};
render() {
return null;
}
}
export default () => (
<Location>
{({ location }) => <ManageScrollImpl location={location} />}
</Location>
);
@okvv
Copy link

okvv commented Dec 23, 2019

Why not refactor componentDidUpdate block to:

const vistedLocationPosition = scrollPositions[this.props.location.key]
window.scrollTo(0, vistedLocationPosition || 0)

@aroraenterprise
Copy link

aroraenterprise commented Apr 2, 2020

For anyone looking for a functional component version of managing scroll position. I just import this component below my router <Router>...routes</Router><ManageScroll />

import { Location, WindowLocation } from "@reach/router";
import React from "react";

let scrollPositions: { [key: string]: number } = {};

type Props = {
	location: WindowLocation;
}

const ManageScrollImpl = ({ location }: Props) => {

	React.useEffect(() => {
		if (location.href) {
			window.scrollTo(0, scrollPositions[location.href || 0]);
		}
		window.addEventListener('scroll', listener);
		return () => window.removeEventListener('scroll', listener);
	}, [location?.href])

	const listener = () => {
		if (location && location.href) {
			scrollPositions[location.href] = window.scrollY;
		}
	};

	return null;
}

export const ManageScroll = () => (
	<Location>
		{({ location }) => <ManageScrollImpl location={location} />}
	</Location>
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment