React breadcrumbs component implementation
Your code is looking pretty good. Here's a handful of suggestions you could try:
This part
{labels.map((label, idx) =&gt; &lt;h5 key={idx} onClick={idx &lt; breadcrumbPaths.length ? () =&gt; history.push(breadcrumbPaths[idx]) : null} className={&quot;label2&quot;}&gt;{label}&lt;/h5&gt;)}

is a really long line of code. Try breaking it up, it makes it easier to read.
{labels.map((label, idx) =&gt; (
  &lt;h5
    key={idx}
    onClick={
      idx &lt; breadcrumbPaths.length
        ? () =&gt; history.push(breadcrumbPaths[idx])
        : null
    }
    className={&quot;label2&quot;}
  &gt;
    {label}
  &lt;/h5&gt;
))}

(I tend to prefer 2-space indentation with javascript and HTML as they both tend to be indentation heavy, and it seems to be a more common in the javascript community - so I'll use that in these examples)
Also, refrain from using an index for an element key when possible (the react docs talk about why). You could instead use the breadcrumbPath, as that would be unique to each element, and the keys would correctly change when the path changes.
{labels.map((label, idx) =&gt; (
  &lt;h5
    key={breadcrumbPaths[idx]}
    onClick={...}
    className={&quot;label2&quot;}
  &gt;
    {label}
  &lt;/h5&gt;
))}

You have some logic in there to calculate the number of backslashes a URL contains, but if you just wait a little bit on that early return, you will already have easy access to that number, as its the same as breadcrumbsPath.length + 1
if (breadcrumbPaths.length + 1 &lt; labels.length) {
  return null;
}

On that note, this function won't handle the case correctly when there's a leading slash on the URL (i.e. 'example.com/a/b/') - that'll need to be taken care of. If you use the above code snippet, then you will only need to fix this issue in one place instead of two - where you create the breadcrumbPaths array.
To address your concern of having multiple returns: there's nothing wrong with having multiple returns like that in a function - in fact, it can often lead to cleaner code. Often, the alternative means large if-thens or flag variables, both of which are much harder to follow. I've heard that once upon a time a function with a single exit used to be something encouraged, but that's not the case anymore.
Now onto the part that you probably care about most - what to do about that chunk of logic with the c-style for loop, and multiple pathNameIdx--s.
First things first, I would probably break the meat of that logic out into a helper function. There's a lot of low-level work going on there that gets in the way of reading and understanding your component.
Here's how your component might look after doing that
import React from &quot;react&quot;;
import { useHistory, useLocation } from &quot;react-router-dom&quot;;

const RouteBreadcrumbs = ({labels = []}) =&gt; {
  const location = useLocation();
  const history = useHistory();
  const pathName = location.pathname;

  const breadcrumbPaths = ancestorPaths(pathName);
  if (breadcrumbPaths.length + 1 &lt; labels.length) {
    return null;
  }

  return (
    &lt;div&gt;
      {labels.map((label, idx) =&gt; (
        &lt;h5
          key={breadcrumbPaths[idx]}
          onClick={
            idx &lt; breadcrumbPaths.length
              ? () =&gt; history.push(breadcrumbPaths[idx])
              : null
          }
          className={&quot;label2&quot;}
        &gt;
          {label}
        &lt;/h5&gt;
      ))}
    &lt;/div&gt;
  )
};

function ancestorPaths(pathName) {
  let breadcrumbPaths = [];
  let pathNameIdx = pathName.length - 1;
  while (true) {
    while (pathName[pathNameIdx] !== &quot;/&quot;) {
      if (pathNameIdx === 1) {
        return breadcrumbPaths;
      }
      pathNameIdx--;
    }

    const newPath = pathName.slice(0, pathNameIdx);
    breadcrumbPaths = [newPath, ...breadcrumbPaths];
    pathNameIdx--;
  }
}

Notice how there's a lot less low-level logic going on in the actual RouteBreadcrumbs component? It's a lot easier to read through it and get a good idea of what's going on - except for maybe the actual jsx getting returned - it's a little too nested for my liking, but it'll get simplified in a bit.
A couple other things I'll note with your original code:

Prefer string.slice() over string.substring() - it has fewer quarks
Good use of console.assert() there. The one thing I dislike about console.assert() is that it doesn't actually throw an error, it just logs one. Sometimes this isn't a big deal, here it is. If that assertion happened to come true, it would be stuck in an infinite loop, logging forever. You can just do if (condition) throw new Error(...) instead, or make your own assert function that actually throws an error.

Now lets look at simplifying our new ancestorPaths() helper function. It is possible to use regex to gather the indicies of all the slashes, which would work similar to how you have it, but greatly simplify the logic (see here). I'm going to instead just split on '/', build a list, and use a generator function, as follows:
function* iterAncestorPaths(pathName) {
  const parts = pathName.split(&quot;/&quot;).filter(x =&gt; x !== &quot;&quot;);
  for (let i = 1; i &lt; parts.length; ++i) {
    yield &quot;/&quot; + parts.slice(0, i).join(&quot;/&quot;);
  }
}

Note that the .filter() at the beginning will take care of both the leading / and a potential trailing slash.
One final thing: If your breadcrumb segments are links, why not make them actual links? it'll simplify some things.
Here's the final solution, with a couple other misc tweaks.
import React from &quot;react&quot;;
import { Link, useLocation } from &quot;react-router-dom&quot;;

const RouteBreadcrumbs = ({labels = []}) =&gt; {
  const pathName = useLocation().pathname;

  const ancestorPaths = [...iterAncestorPaths(pathName)];
  if (ancestorPaths.length + 1 &lt; labels.length) {
    return null;
  }

  return (
    &lt;div&gt;
      {ancestorPaths.map((path, idx) =&gt; (
        &lt;Link key={path} to={path} className=&quot;label&quot;&gt;
          {labels[idx]}
        &lt;/Link&gt;
      ))}
      &lt;span className=&quot;label&quot;&gt;{labels[labels.length - 1]}&lt;/span&gt;
    &lt;/div&gt;
  );
};

function* iterAncestorPaths(pathName) {
  const parts = pathName.split(&quot;/&quot;).filter(x =&gt; x !== &quot;&quot;);
  for (let i = 1; i &lt; parts.length; ++i) {
    yield &quot;/&quot; + parts.slice(0, i).join(&quot;/&quot;);
  }
}