/* * Use this AnchorLink component instead of your normal tag for page anchors * * RouteContext.Consumer here is basically passing history object * which is available as props with Gatsy’s layout and all page components * you don’t have to use context if you don’t want to * * callback is optional */ import React from 'react' import { string, node, func } from 'prop-types' import { scrollToHref } from '../../utils/helpers/scroll' import RouteContext from '../../contexts/route' const handleClick = ({ href, callback, history, event, }) => { /* prevent normal link behavior */ event.preventDefault() /* temporarily hijack the window event handler */ const tempFuncHolder = window.onhashchange window.onhashchange = undefined /* invoke the scroll function (always, regardless of browser history push) */ scrollToHref(href) /* * push to browser history, but only if it’s a new anchor * this fixes a bug in Gatsby where you can keep on clicking * the same anchor over and over again, tainting history */ if (history && history.location.hash !== href) { history.push(href) } /* perform callback (example: closing modal sidebar) */ if (callback) { callback() } /* return what you hijacked */ window.onhashchange = tempFuncHolder } export default function AnchorLink({ href, callback, children, ...restProps }) { return ( {({ history }) => ( handleClick({ href, callback, history, event, }) } {...restProps} > {children} )} ) } AnchorLink.propTypes = { href: string.isRequired, callback: func, children: node.isRequired, } AnchorLink.defaultProps = { callback: undefined, }