Skip to content

Commit

Permalink
Do not pass ref to functional components w/out forwardRef
Browse files Browse the repository at this point in the history
If we can't use forwardRef, we shouldn't ever pass a ref to a
functional component. Use innerRef workaround instead.

Fixes #6934
  • Loading branch information
mjackson committed Sep 27, 2019
1 parent 55695fa commit 375f320
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 16 deletions.
19 changes: 14 additions & 5 deletions packages/react-router-dom/modules/Link.js
Expand Up @@ -5,9 +5,10 @@ import invariant from "tiny-invariant";
import { resolveToLocation, normalizeToLocation } from "./utils/locationUtils";

// React 15 compat
const forwardRefShim = C => C;
let { forwardRef } = React;
if (typeof forwardRef === "undefined") {
forwardRef = C => C;
forwardRef = forwardRefShim;
}

function isModifiedEvent(event) {
Expand Down Expand Up @@ -70,18 +71,26 @@ const Link = forwardRef(
);

const href = location ? history.createHref(location) : "";

return React.createElement(component, {
const props = {
...rest,
ref: forwardedRef || innerRef,
href,
navigate() {
const location = resolveToLocation(to, context.location);
const method = replace ? history.replace : history.push;

method(location);
}
});
};

// React 15 compat
if (forwardRefShim !== forwardRef) {
props.ref = forwardedRef || innerRef;
} else {
// TODO: deprecate
props.innerRef = innerRef;
}

return React.createElement(component, props);
}}
</RouterContext.Consumer>
);
Expand Down
30 changes: 19 additions & 11 deletions packages/react-router-dom/modules/NavLink.js
Expand Up @@ -6,9 +6,10 @@ import Link from "./Link";
import { resolveToLocation, normalizeToLocation } from "./utils/locationUtils";

// React 15 compat
const forwardRefShim = C => C;
let { forwardRef } = React;
if (typeof forwardRef === "undefined") {
forwardRef = C => C;
forwardRef = forwardRefShim;
}

function joinClassnames(...classnames) {
Expand Down Expand Up @@ -67,16 +68,23 @@ const NavLink = forwardRef(
: classNameProp;
const style = isActive ? { ...styleProp, ...activeStyle } : styleProp;

return (
<Link
ref={forwardedRef || innerRef}
aria-current={(isActive && ariaCurrent) || null}
className={className}
style={style}
to={toLocation}
{...rest}
/>
);
const props = {
"aria-current": (isActive && ariaCurrent) || null,
className,
style,
to: toLocation,
...rest
};

// React 15 compat
if (forwardRefShim !== forwardRef) {
props.ref = forwardedRef || innerRef;
} else {
// TODO: deprecate
props.innerRef = innerRef;
}

return <Link {...props} />;
}}
</RouterContext.Consumer>
);
Expand Down

0 comments on commit 375f320

Please sign in to comment.