diff --git a/packages/react-router-dom/.size-snapshot.json b/packages/react-router-dom/.size-snapshot.json index 0b5a9d48dc..bd0135f9b8 100644 --- a/packages/react-router-dom/.size-snapshot.json +++ b/packages/react-router-dom/.size-snapshot.json @@ -1,26 +1,26 @@ { "esm/react-router-dom.js": { - "bundled": 8874, - "minified": 5312, - "gzipped": 1711, + "bundled": 8700, + "minified": 5180, + "gzipped": 1664, "treeshaked": { "rollup": { - "code": 508, - "import_statements": 417 + "code": 379, + "import_statements": 355 }, "webpack": { - "code": 1800 + "code": 1612 } } }, "umd/react-router-dom.js": { - "bundled": 159933, - "minified": 56923, - "gzipped": 16433 + "bundled": 159744, + "minified": 56768, + "gzipped": 16411 }, "umd/react-router-dom.min.js": { - "bundled": 96671, - "minified": 33875, - "gzipped": 9980 + "bundled": 96492, + "minified": 33716, + "gzipped": 9979 } } diff --git a/packages/react-router-dom/modules/Link.js b/packages/react-router-dom/modules/Link.js index dc59204632..a99b869bbd 100644 --- a/packages/react-router-dom/modules/Link.js +++ b/packages/react-router-dom/modules/Link.js @@ -8,63 +8,66 @@ function isModifiedEvent(event) { return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); } -/** - * The public API for rendering a history-aware . - */ -class Link extends React.Component { - handleClick(event, context) { - try { - if (this.props.onClick) this.props.onClick(event); - } catch (ex) { - event.preventDefault(); - throw ex; - } - - if ( - !event.defaultPrevented && // onClick prevented default - event.button === 0 && // ignore everything but left clicks - (!this.props.target || this.props.target === "_self") && // let browser handle "target=_blank" etc. - !isModifiedEvent(event) // ignore clicks with modifier keys - ) { - event.preventDefault(); +function LinkAnchor({ innerRef, navigate, onClick, ...rest }) { + const { target } = rest; - const location = resolveToLocation(this.props.to, context.location); + return ( + { + try { + if (onClick) onClick(event); + } catch (ex) { + event.preventDefault(); + throw ex; + } - const method = this.props.replace - ? context.history.replace - : context.history.push; + if ( + !event.defaultPrevented && // onClick prevented default + event.button === 0 && // ignore everything but left clicks + (!target || target === "_self") && // let browser handle "target=_blank" etc. + !isModifiedEvent(event) // ignore clicks with modifier keys + ) { + event.preventDefault(); + navigate(); + } + }} + /> + ); +} - method(location); - } - } +/** + * The public API for rendering a history-aware . + */ +function Link({ component = LinkAnchor, replace, to, ...rest }) { + return ( + + {context => { + invariant(context, "You should not use outside a "); - render() { - const { innerRef, replace, to, ...rest } = this.props; // eslint-disable-line no-unused-vars + const { history } = context; - return ( - - {context => { - invariant(context, "You should not use outside a "); + const location = normalizeToLocation( + resolveToLocation(to, context.location), + context.location + ); - const location = normalizeToLocation( - resolveToLocation(to, context.location), - context.location - ); + const href = location ? history.createHref(location) : ""; - const href = location ? context.history.createHref(location) : ""; + return React.createElement(component, { + ...rest, + href, + navigate() { + const location = resolveToLocation(to, context.location); + const method = replace ? history.replace : history.push; - return ( - this.handleClick(event, context)} - href={href} - ref={innerRef} - /> - ); - }} - - ); - } + method(location); + } + }); + }} + + ); } if (__DEV__) { @@ -73,14 +76,14 @@ if (__DEV__) { PropTypes.object, PropTypes.func ]); - const innerRefType = PropTypes.oneOfType([ + const refType = PropTypes.oneOfType([ PropTypes.string, PropTypes.func, PropTypes.shape({ current: PropTypes.any }) ]); Link.propTypes = { - innerRef: innerRefType, + innerRef: refType, onClick: PropTypes.func, replace: PropTypes.bool, target: PropTypes.string, diff --git a/packages/react-router-dom/modules/__tests__/Link-test.js b/packages/react-router-dom/modules/__tests__/Link-test.js index ff16eedd6f..5fa6f543db 100644 --- a/packages/react-router-dom/modules/__tests__/Link-test.js +++ b/packages/react-router-dom/modules/__tests__/Link-test.js @@ -120,12 +120,10 @@ describe("A ", () => { }); }); - it("exposes its ref via an innerRef callback prop", done => { + it("exposes its ref via an innerRef callbar prop", () => { + let refNode; function refCallback(n) { - if (n) { - expect(n.tagName).toEqual("A"); - done(); - } + refNode = n; } renderStrict( @@ -136,6 +134,30 @@ describe("A ", () => { , node ); + + expect(refNode).not.toBe(undefined); + expect(refNode.tagName).toEqual("A"); + }); + + it("uses a custom component prop", () => { + let linkProps; + function MyComponent(p) { + linkProps = p; + return null; + } + + renderStrict( + + + link + + , + node + ); + + expect(linkProps).not.toBe(undefined); + expect(typeof linkProps.href).toBe("string"); + expect(typeof linkProps.navigate).toBe("function"); }); it("exposes its ref via an innerRef RefObject prop", done => {