Skip to content

Commit

Permalink
feat: Migrate SafeAnchor to be a ref forwarder
Browse files Browse the repository at this point in the history
This comes with a minor fix to Button not passing the ref to the
right prop to SafeAnchor.
  • Loading branch information
bpas247 committed Jul 28, 2019
1 parent f16d29b commit fc41617
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 45 deletions.
2 changes: 1 addition & 1 deletion src/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const Button = React.forwardRef(
<SafeAnchor
{...props}
as={as}
innerRef={ref}
ref={ref}
className={classNames(classes, props.disabled && 'disabled')}
/>
);
Expand Down
79 changes: 35 additions & 44 deletions src/SafeAnchor.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ const propTypes = {
* this is sort of silly but needed for Button
*/
as: PropTypes.elementType,

/** @private */
innerRef: PropTypes.any,
};

function isTrivialHref(href) {
Expand All @@ -31,47 +28,40 @@ function isTrivialHref(href) {
* button its accessible. It also emulates input `disabled` behavior for
* links, which is usually desirable for Buttons, NavItems, DropdownItems, etc.
*/
class SafeAnchor extends React.Component {
constructor(props, context) {
super(props, context);

this.handleClick = this.handleClick.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
}

handleClick(event) {
const { disabled, href, onClick } = this.props;

if (disabled || isTrivialHref(href)) {
event.preventDefault();
}

if (disabled) {
event.stopPropagation();
return;
}

if (onClick) {
onClick(event);
}
}

handleKeyDown(event) {
if (event.key === ' ') {
event.preventDefault();
this.handleClick(event);
}
}

render() {
const {
const SafeAnchor = React.forwardRef(
(
{
// Need to define the default "as" during prop destructuring to be compatible with styled-components github.com/react-bootstrap/react-bootstrap/issues/3595
as: Component = 'a',
disabled,
onKeyDown,
innerRef,
...props
} = this.props;
},
ref,
) => {
const handleClick = event => {
const { href, onClick } = props;

if (disabled || isTrivialHref(href)) {
event.preventDefault();
}

if (disabled) {
event.stopPropagation();
return;
}

if (onClick) {
onClick(event);
}
};

const handleKeyDown = event => {
if (event.key === ' ') {
event.preventDefault();
handleClick(event);
}
};

if (isTrivialHref(props.href)) {
props.role = props.role || 'button';
Expand All @@ -84,16 +74,17 @@ class SafeAnchor extends React.Component {
props.tabIndex = -1;
props['aria-disabled'] = true;
}
if (innerRef) props.ref = innerRef;

return (
<Component
ref={ref}
{...props}
onClick={this.handleClick}
onKeyDown={createChainedFunction(this.handleKeyDown, onKeyDown)}
onClick={handleClick}
onKeyDown={createChainedFunction(handleKeyDown, onKeyDown)}
/>
);
}
}
},
);

SafeAnchor.propTypes = propTypes;

Expand Down

0 comments on commit fc41617

Please sign in to comment.