Reputation: 2297
When I type "/create"
after the address, I expect it shows Home
component. Since I don't use from exact
prop. Because path='/c'
matches with "/create"
, but it shows Create
component. It first worked fine and when I used from exact
prop it worked fine as expected. I don't know why it does not work as expected after I removed exact
from the first Route
.
It works fine only if I do: <Route path="/" element={<Home />} />
Note: I used this for run server: npx json-server --watch data/db.json --port 8000
See that on Codesandbox: https://codesandbox.io/s/epic-feather-uz2iur
It's the section of my Routes:
function App() {
return (
<Router>
<div className="App">
<Navbar />
<div className="content">
<Routes>
<Route path="/c" element={<Home />} />
<Route path="/create" element={<Create />} />
</Routes>
</div>
</div>
</Router>
);
}
It gives the same result on my Webstorm(react-router-dom version 5):
<Router>
<div className="App">
<Navbar />
<div className="content">
<Switch>
<Route path="/">
<Home />
</Route>
<Route path="/create">
<Create />
</Route>
</Switch>
</div>
</div>
</Router>
Upvotes: 1
Views: 105
Reputation: 202605
It seems the issue is a misunderstanding of how route path matching changed from react-router@5
to react-router@6
.
In RRDv5 the route path was more of a "path prefix", meaning it behaved like you described. A path="/c"
could match any URL path starting with "/c"
. This had its peculiarities when trying to specifically, or exactly, match certain routes. This is often why naive devs would pepper all their routes with the exact
prop (because not understanding how matching worked).
For example, your v5 version, it would need to use the exact
prop in order to match "/c"
exactly and render the Home
component, or not match exactly so the Create
component could be matched.
<Router>
<div className="App">
<Navbar />
<div className="content">
<Switch>
<Route exact path="/c" component={Home} />
<Route exact path="/create" component={Create} />
</Switch>
</div>
</div>
</Router>
This is because of (A) the way route matching works in v5, and (B) the way the Switch
component renders only the first matching Route
or Redirect
component. The route path order and specificity matters! In almost 100% of the use cases you don't need the exact
prop by simply ordering your routes correctly, from most specific to least specific.
The same v5 routes and switch, but ordered correctly:
<Router>
<div className="App">
<Navbar />
<div className="content">
<Switch>
<Route path="/create" component={Create} />
<Route path="/c" component={Home} />
</Switch>
</div>
</div>
</Router>
Note now that "/c"
can't match to path="/create"
and matching continues down until it finds and matches path="/c"
.
In RRDv6 paths are now always exactly matched, so the exact
prop no longer exists as it's not needed. Each route uses a path ranking system, see Ranking Routes. The specificity of the path yields a rank value and this is used to match a route. Route order is now irrelevant.
<Routes>
{/* match & render when path is exactly "/c" */}
<Route path="/c" element={<Home />} />
{/* match & render when path is exactly "/create" */}
<Route path="/create" element={<Create />} />
</Routes>
Upvotes: 2
Reputation: 1450
There was a breaking change in v6 regarding "exact" prop - it does not exist anymore and all paths are by default exact.
You can read more here: upgrading to v6
Route exact is gone. Instead, routes with descendant routes (defined in other components) use a trailing * in their path to indicate they match deeply
Upvotes: 1
Reputation: 10463
Using react-router-dom
version 5 you can use Switch
along with *
and it should work
<Router>
<div className="App">
<Navbar />
<div className="content"></div>
<Switch>
<Route path="/c*">
<Home />
</Route>
<Route path="/create">
<Create />
</Route>
</Switch>
</div>
</Router>
According to documentation
A
Switch
looks through all its children elements and renders the first one whose path matches the current URL. Use a any time you have multiple routes, but you want only one of them to render at a time
Upvotes: 1