I have a certain generic link component (an atom, I am using Atomic design for structuring my React app), which either returns just a <span>
with a Title and arrow icon or when it does have a url
it returns a react-router-dom <Link>
.
I am using react-router-dom v5.
import React from 'react';
import { Link } from 'react-router-dom';
import { Arrow} from 'app/icons';
import { Props } from './MyLink.types';
const MyLink = ({ variant = 'iconRight', text, url }: Props) => {
const renderLinkBody = () => {
return (
<React.Fragment>
<span css={styles.label}>{text}</span>
<Arrow />
</React.Fragment>
);
};
return url !== undefined ? (
<Link to={url} title={text} >
{renderLinkBody()}
</Link>
) : (
<span>{renderLinkBody()}</span>
);
};
export default MyLink;
Now I want to use this component for creating a Back button (similar behaviour as the browser back button).
Is it a clean approach passing an onClick prop (function) from parent to child, something like:
const history = useHistory();
<MyLink text="My title" variant="iconLeft" onClick={history.goBack} />
and then adjust MyLink component a bit:
return url !== undefined || onClick ? (
<Link to={url} title={text} onClick={onClick} >
{renderLinkBody()}
</Link>
) : (
<span>{renderLinkBody()}</span>
);
I think this approach isn't bad. When attaching an onClick
handler to the Link
component you will likely need to prevent the default link behavior from occurring. You will also need to provide a valid to
prop to the Link
component when using a click handler.
Example:
const MyLink = ({ variant = "iconRight", onClick, text, url }) => {
const clickHandler = e => {
if (onClick) {
e.preventDefault();
onClick();
}
};
const renderLinkBody = () => {
return (
<>
<span css={styles.label}>{text}</span>
<Arrow />
</>
);
};
return url !== undefined || onClick ? (
<Link to={url || "/"} title={text} onClick={clickHandler} >
{renderLinkBody()}
</Link>
) : (
<span>{renderLinkBody()}</span>
);
};
Because of the issue with the onClick
and the Link
action, you may want to make the "back" navigation a button instead, and refactor MyLink
to conditionally render the button, the link, or the span, depending on needs.