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 => {