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:
- I split the string by
/
. As a result, I get an array. - I find the last item (the one I want to get rid of).
- I iterate through the array and filter the item I don't want. Using
.filter
. I get another array. - 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;
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;
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.
Top comments (0)