In React Router v5 and earlier, it was essential to wrap your route definitions with the <Switch>
component. The <Switch>
component ensures that only one route is rendered at a time. Without <Switch>
, React Router would render all matching routes, which could lead to unexpected behavior, as more than one component would be displayed simultaneously.
In React Router v6, the <Switch>
component was replaced with <Routes>
, which automatically behaves like the old <Switch>
, ensuring only one route is rendered.
However, for React Router v5 and earlier, forgetting to add <Switch>
can cause multiple routes to render when only one should be displayed.
Common Issue:
If you forget to add <Switch>
, React Router may match multiple routes, and all of them could be rendered simultaneously, leading to visual confusion and unexpected behavior in your app.
Example of Issue (React Router v5):
import React from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
function Home() {
return <h2>Home Page</h2>;
}
function About() {
return <h2>About Page</h2>;
}
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
</Router>
);
}
export default App;
Issue:
- In the code above, without the
<Switch>
wrapper, both routes (/
and/about
) can be matched and rendered simultaneously if they overlap. For example, visiting/about
might render both theHome
andAbout
components because the router doesn’t know which one to prioritize.
Solution: Add <Switch>
to Ensure Only One Route is Rendered
To fix this, wrap your routes with the <Switch>
component. The <Switch>
ensures that only the first route that matches the current URL is rendered.
Corrected Example with <Switch>
(React Router v5):
import React from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
function Home() {
return <h2>Home Page</h2>;
}
function About() {
return <h2>About Page</h2>;
}
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
</Router>
);
}
export default App;
Explanation:
- The
<Switch>
component ensures that only one route will be rendered at a time. It will stop looking for further matches once it finds the first match. - The
exact
prop is used on the/
route to make sure it only matches the home route (/
) and not any other routes that start with/
(like/about
).
React Router v6: No Need for <Switch>
In React Router v6, the Switch
component was replaced by the <Routes>
component, which automatically handles the behavior of rendering only the first matching route.
In v6, you no longer need to use <Switch>
or exact
. All routes now match exactly by default.
Example in React Router v6 (No <Switch>
Needed):
import React from 'react';
import { BrowserRouter as Router, Route, Link, Routes } from 'react-router-dom';
function Home() {
return <h2>Home Page</h2>;
}
function About() {
return <h2>About Page</h2>;
}
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Router>
);
}
export default App;
Explanation:
<Routes>
behaves like the old<Switch>
, ensuring that only one route is matched and rendered.- There is no need for the
exact
prop because all routes are matched exactly by default.
Key Points to Remember:
- In React Router v5 and earlier:
- Always wrap your routes in a
<Switch>
to ensure only one route is rendered at a time. - Use the
exact
prop to ensure that the route for/
only matches the home route and does not interfere with other routes like/about
.
- Always wrap your routes in a
- In React Router v6:
- The
<Switch>
component is replaced by<Routes>
, which automatically ensures that only one route is rendered. - There is no need to use the
exact
prop anymore as routes now match exactly by default.
- The
- Route Order:
- In both v5 and v6, the order of routes matters. Place the most specific routes first and the catch-all routes last to prevent them from matching prematurely.
Example of Unexpected Behavior Without <Switch>
(React Router v5):
import React from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
function Home() {
return <h2>Home Page</h2>;
}
function About() {
return <h2>About Page</h2>;
}
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
{/* Missing <Switch> */}
<Route path="/" component={Home} /> {/* This may match /about as well */}
<Route path="/about" component={About} />
</Router>
);
}
export default App;
Issue:
- Without
<Switch>
, both theHome
andAbout
components could be rendered when navigating to/about
, which is not the desired behavior.
Corrected Example with <Switch>
(React Router v5):
import React from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
function Home() {
return <h2>Home Page</h2>;
}
function About() {
return <h2>About Page</h2>;
}
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
</Router>
);
}
export default App;