Skip to content

Instantly share code, notes, and snippets.

@gajus
Last active February 8, 2021 11:28
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save gajus/0bbc78135d88a02c18366f12237011a5 to your computer and use it in GitHub Desktop.
Save gajus/0bbc78135d88a02c18366f12237011a5 to your computer and use it in GitHub Desktop.
// @flow
/**
* @param history {@see https://www.npmjs.com/package/history}
* @param timeout A number of milliseconds to wait for the element to appear after PUSH action has been received.
*/
export default (history: *, timeout: number = 1000) => {
let observer;
let timeoutId;
if (!window.MutationObserver) {
return;
}
const reset = () => {
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
if (observer) {
observer.disconnect();
}
};
const createScrollToElement = (id: string) => {
return () => {
const element = document.getElementById(id);
if (element) {
element.scrollIntoView();
reset();
return true;
}
return false;
};
};
history.listen((location: *, action: *) => {
if (timeoutId) {
reset();
}
if (action !== 'PUSH') {
return;
}
if (typeof location.hash !== 'string') {
return;
}
const elementId = location.hash.slice(1);
if (!elementId) {
return;
}
const scrollToElement = createScrollToElement(elementId);
setTimeout(() => {
if (scrollToElement()) {
return;
}
observer = new MutationObserver(scrollToElement);
observer.observe(document, {
attributes: true,
childList: true,
subtree: true
});
timeoutId = setTimeout(reset, timeout);
});
});
};
@aditya-padhi-kbl
Copy link

Nice information. But can you please guide me how to implement this in a react app ?

@prmichaelsen
Copy link

prmichaelsen commented Jun 10, 2020

@aditya-padhi-kbl it's simple

import React from 'react'; 
import { useHistory } from 'react-router-dom';
import Adventure from './Adventure';
// I named it `useAnchors`
import { useAnchors } from './useAnchors';

export const App = withContainer(() => {
  const history = useHistory();
  useAnchors(history, 750);
  return (
    <Adventure/>
  );
});

export default App;

@aditya-padhi-kbl
Copy link

aditya-padhi-kbl commented Jun 10, 2020 via email

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