Search code examples
reactjsreact-hooksreact-router-domreact-component

Creating a history back link and make use of my existing link component


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>
  );

Solution

  • 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>
      );
    };
    

    Edit react-creating-a-history-back-link-and-make-use-of-my-existing-link-component

    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.