Dynamic back button in your React app

Pere Sola - Oct 2 '20 - - Dev Community

Today I was working on my url-shortener React and Node app. I am at the stage where I am building the admin panel, where I can approve Users, see who has signed up, etc. Each of these pages is a component and it has a back button. Since I found myself coding a back button in each of these components, I asked myself how could I write DRYer code - a dynamic back button that would send user a page up in the url path:

For instance, if someone is in /admin/approveusers back button would bring Users to /admin. The same button, when placed in Component sitting in /admin/allusers would bring folks to /admin.

I started to rummage in the react-router-dom properties: location, history, match. I found no property that would contain the existing path minus a level. Maybe I missed it or indeed it doesn't exist (I had to try!). There is a goBack() method in history which was interesting. However, it seemed like a bad idea - even though I expect Users to enter the Component that has the back button by parent path, someone may end up in the Component as a result of typing the direct url. In that case, the back button using goBack() method in history would create a mess.

I didn't do much research online, and settled with the following. Maybe it is a hack, maybe it is best practice, maybe it's horrible, please let me know in the comments! It works, which is what matters at the end of the day.

I am using the match.path react-router-dom property, which contains the path of the component: i.e. /admin/active. With that, I do the following:

  1. I split the string by /. As a result, I get an array.
  2. I find the last item (the one I want to get rid of).
  3. I iterate through the array and filter the item I don't want. Using .filter. I get another array.
  4. I join the array with '/' and voilà, I get the path one level up i.e. '/admin' instead of '/admin/active'.

See below my component:

import React from 'react';
import { Link } from 'react-router-dom';

const BackButton = ({ match }) => {
    const arr = match.path.split('/');
    const currPage = arr[arr.length - 1];
    const parentPath = arr
        .filter((item) => {
            return item !== currPage;
        })
        .join('/');
    return <Link to={parentPath}>{`<-- Back`}</Link>;
};

export default BackButton;
Enter fullscreen mode Exit fullscreen mode

EDIT 03/10/2020

What if I use the BackButton component in the top level of the path (/)? In that case, there is not one level up to go back to. I refactored my Component to the following:

import React from 'react';
import { Link } from 'react-router-dom';

const BackButton = ({ match, destination }) => {
    let parentPath;
    if (match.path === '/') {
        parentPath = `/${destination}`;
    } else {
        const arr = match.path.split('/');
        const currPage = arr[arr.length - 1];
        parentPath = arr
            .filter((item) => {
                return item !== currPage;
            })
            .join('/');
    }
    return (
        <Link to={parentPath}>
            {match.path === '/'
                ? `<-- ${destination.charAt(0).toUpperCase() + destination.slice(1)}`
                : '<-- Back'}
        </Link>
    );
};

export default BackButton;
Enter fullscreen mode Exit fullscreen mode

I have added a destination prop (that I am defining in the parent Component i.e. destination='login'. I collect that destination and I use it when match.path === '/'. In that case, I set parentPath to /${destination} and the text in the link becomes whatever string coming from the destination prop with the first letter in capital letter.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .