Search code examples
reactjsmaterial-uibreadcrumbs

How to handle dynamic breadcrumbs in react JS , when we pass an id in the URL (MUI breadcrumbs with react-router-dom)?


import { Box, Breadcrumbs, Typography } from "@mui/material";
import React from "react";
import { Link, useLocation } from "react-router-dom";
import { storage } from "../../config/storage";
import "../Custom/CSS/HeaderCrums.css";

const HeaderCrums = () => {
  const location = useLocation();
  let pathnames = location.pathname.split("/").filter((x) => x);
  const lastIndex = pathnames.length - 1;
  if (pathnames[lastIndex].length > 20) {
    pathnames.splice(lastIndex, 1);
  }
  const id = storage.fetch.prev_id("prev_id");

  return (
    <Box sx={style.box}>
      <Breadcrumbs sx={{ pt: "14px", pb: "14px" }} aria-label="breadcrumb">
        <Link className="linkText" to={"/"}>
          Home
        </Link>
        {pathnames.map((name, index) => {
          const routeTo = `/${pathnames.slice(0, index + 1).join(`/${id}`)}`;
          const lastIndex = index === pathnames.length - 1;
          
          return !lastIndex ? (
            <Link
              className={
                index === pathnames.length - 1 ? "linkText2" : "linkText"
              }
              to={routeTo}
            >
              {name.length < 20 ? name : ""}
            </Link>
          ) : (
            <Typography
              sx={{
                textTransform: "uppercase",
                fontSize: "14px",
                fontWeight: "600",
              }}
            >
              {name}
            </Typography>
          );
        })}
      </Breadcrumbs>
    </Box>
  );
};

And my URL is http://localhost:3000/card/viewdetail/eyJpdiI6IkhETWtQSkFiVDVVSnd2eWtnVERHTGc9PSIsInZh

I am tried with the help of react hooks (useLocation) but how can I split a id in array and link breadcrumbs to previous pages


Solution

  • You do not need to use 'useLocation' method from the 'react router dom' you can simply utilize window object since React has access to it. Below solution includes typescript already, you can remove typing and you would get clean React JS.

    First thing you do is a creation of the breadcrumbs object that reads values from the url pathname:

      const paths = window.location.pathname.split('/').slice(1)
    
      const breadcrumbs: { title: string; link: string }[] = []
      paths.map((p, index) => {
        breadcrumbs.push({
          title: `${p}`,
          link: `/${paths.slice(0, index + 1).join('/')}`,
        })
      })
    

    In next step use map to iterate through 'breadcrumbs' object with your 'MUI breadcrumbs component' like this:

            <Breadcrumbs aria-label='breadcrumb'>
            {breadcrumbs &&
              breadcrumbs.map((b, index) =>
                index !== breadcrumbs.length - 1 ? (
                  <Box key={b.title}>
                    <Link underline='hover' color='inherit' href={b.link}>
                      {b.title}
                    </Link>
                  </Box>
                ) : (
                  <Typography key={b.title} color='text.primary'>
                    {b.title}
                  </Typography>
                ),
              )}
          </Breadcrumbs>
    

    Full example:

    import { Box, Breadcrumbs, Typography, Link } from '@mui/material'
    
    export function HeaderCrums(): JSX.Element {
    
      const paths = window.location.pathname.split('/').slice(1)
    
      const breadcrumbs: { title: string; link: string }[] = []
      paths.map((p, index) => {
        breadcrumbs.push({
          title: `${p}`,
          link: `/${paths.slice(0, index + 1).join('/')}`,
        })
      })
    
      return (
        <Breadcrumbs aria-label='breadcrumb'>
          {breadcrumbs &&
            breadcrumbs.map((b, index) =>
              index !== breadcrumbs.length - 1 ? (
                <Box key={b.title}>
                  <Link underline='hover' color='inherit' href={b.link}>
                    {b.title}
                  </Link>
                </Box>
              ) : (
                <Typography key={b.title} color='text.primary'>
                  {b.title}
                </Typography>
              ),
            )}
        </Breadcrumbs>
      )
    }