react-router icon indicating copy to clipboard operation
react-router copied to clipboard

[Bug]: <Route path="/"><Route path="*" /><Route /> doesn't match

Open tiltysola opened this issue 3 years ago • 2 comments
trafficstars

What version of React Router are you using?

6.2.1

Steps to Reproduce

Case 1:

    <Routes>
      <Route path="/" element={<Layout />}>
        <Route path="a" element={<Custom text="a" />}>
          <Route path="b" element={<Custom text="b" />} />
          <Route path="*" element={<Notfound />} />
        </Route>
        <Route path="*" element={<Notfound />} />
      </Route>
    </Routes>

Case 2:

    <Routes>
      <Route path="/" element={<Layout />}>
        <Route path="a/*" element={<Custom text="a" />}>
          <Route path="b" element={<Custom text="b" />} />
          <Route path="*" element={<Notfound />} />
        </Route>
        <Route path="*" element={<Notfound />} />
      </Route>
    </Routes>

Expected Behavior

Case 1 === Case 2

Actual Behavior

Visit path /a it response:

Case 1:

Layout
a

Case 2:

Layout
a
NotFound

tiltysola avatar Dec 21 '21 09:12 tiltysola

Moreover NavLink returns isActive: false for child routes

Yegorich555 avatar Feb 11 '22 08:02 Yegorich555

I am also encountering this issue. I was trying to get the label I put on the route with the longest match. If it's helpful to anyone in the future, I solved my problem with this snippet:

const location = useLocation()
  const getLongestRouteMatch = useMemo((): ReactNode => {
    const locationPathArray = location.pathname.split('/')
    const longestMatch: { routeArray: string[]; label: string } = {
      routeArray: [],
      label: '',
    }
    for (const [_, route] of Object.entries(TechnicianRoutes)) {
      const routePathArray = route.PATH.split('/')
      for (let i = 0; i < routePathArray.length; i++) {
        const matchesWildcard =
          (locationPathArray[i] && routePathArray[i].startsWith(':')) ||
          routePathArray[i] === '*'
        if (routePathArray[i] === locationPathArray[i] || matchesWildcard) {
          if (longestMatch.routeArray.length < i + 1) {
            longestMatch.routeArray.push(routePathArray[i])
            longestMatch.label = route.LABEL
          }
        }
      }
    }

    return <div className="card-title-lg"> {longestMatch.label} </div>
  }, [location])

skeptrunedev avatar Dec 01 '22 18:12 skeptrunedev

This issue has been automatically marked stale because we haven't received a response from the original author in a while 🙈. This automation helps keep the issue tracker clean from issues that are not actionable. Please reach out if you have more information for us or you think this issue shouldn't be closed! 🙂 If you don't do so within 7 days, this issue will be automatically closed.

github-actions[bot] avatar Apr 25 '23 01:04 github-actions[bot]

I'm going to close this out as expected, since splats change the behavior of the matching logic - and we specifically have tests that repeated splats should continue matching: https://github.com/remix-run/react-router/blob/1143652/packages/react-router/tests/path-matching-test.tsx#L234

brophdawg11 avatar Apr 28 '23 21:04 brophdawg11