diff --git a/src/private/Link.js b/src/private/Link.js index 46204781..d0aa94d8 100644 --- a/src/private/Link.js +++ b/src/private/Link.js @@ -29,57 +29,63 @@ function isExternalLink(external_link, href) { return external_link; } -function Link({ - children, - preOnClick, - target, - linkTarget, - href, - download, - external_link, - disabled, - ...otherProps -}) { - const updateLocation = e => { - const hasModifiers = e.metaKey || e.shiftKey || e.altKey || e.ctrlKey; - if (hasModifiers) { - return; - } - if (disabled) { - e.preventDefault(); - return; - } - if (preOnClick) { - preOnClick(); - } - if (href && !isExternalLink(external_link, href)) { - // prevent anchor from updating location - e.preventDefault(); - window.history.pushState({}, '', href); - window.dispatchEvent(new CustomEvent('_dashprivate_pushstate')); - // scroll back to top - window.scrollTo(0, 0); - } - }; - - const linkIsExternal = href && isExternalLink(external_link, href); - /** - * ideally, we would use cloneElement however - * that doesn't work with dash's recursive - * renderTree implementation for some reason - */ - return ( - updateLocation(e)} - > - {children} - - ); -} +const Link = React.forwardRef( + ( + { + children, + preOnClick, + target, + linkTarget, + href, + download, + external_link, + disabled, + ...otherProps + }, + ref + ) => { + const updateLocation = e => { + const hasModifiers = e.metaKey || e.shiftKey || e.altKey || e.ctrlKey; + if (hasModifiers) { + return; + } + if (disabled) { + e.preventDefault(); + return; + } + if (preOnClick) { + preOnClick(); + } + if (href && !isExternalLink(external_link, href)) { + // prevent anchor from updating location + e.preventDefault(); + window.history.pushState({}, '', href); + window.dispatchEvent(new CustomEvent('_dashprivate_pushstate')); + // scroll back to top + window.scrollTo(0, 0); + } + }; + + const linkIsExternal = href && isExternalLink(external_link, href); + /** + * ideally, we would use cloneElement however + * that doesn't work with dash's recursive + * renderTree implementation for some reason + */ + return ( + updateLocation(e)} + ref={ref} + > + {children} + + ); + } +); Link.propTypes = { /** diff --git a/src/private/__tests__/Link.test.js b/src/private/__tests__/Link.test.js index 8ec4793a..a9243531 100644 --- a/src/private/__tests__/Link.test.js +++ b/src/private/__tests__/Link.test.js @@ -70,7 +70,12 @@ describe('Link', () => { const user = userEvent.setup(); const outerOnClick = jest.fn(); const link = render( -
outerOnClick(e.defaultPrevented)}> +
{ + outerOnClick(e.defaultPrevented); + e.preventDefault(); + }} + > Clickable
); @@ -86,7 +91,12 @@ describe('Link', () => { const user = userEvent.setup(); const outerOnClick = jest.fn(); const link = render( -
outerOnClick(e.defaultPrevented)}> +
{ + outerOnClick(e.defaultPrevented); + e.preventDefault(); + }} + > Clickable