Design Converter
Education
Last updated on Mar 12, 2025
•7 mins read
Last updated on Mar 12, 2025
•7 mins read
How do single-page applications (SPAs) in React handle navigation between views?
React Router makes this easy by managing client-side routing. One key component for handling routes used to be the Switch component. But with updates to React Router, some components, including Switch, have been replaced.
So, how does routing work now?
This blog breaks down how to use the latest React Router features, including the react switch route and its replacements.
Let’s get into the details of how routing works in React.
To begin using React Router, you need to install the react-router-dom package. This can be done using npm or yarn:
1npm install react-router-dom
or
1yarn add react-router-dom
Next, you import BrowserRouter and wrap your app with it:
1import React from 'react'; 2import { BrowserRouter as Router } from 'react-router-dom'; 3 4function App() { 5 return ( 6 <Router> 7 {/* Your app components here */} 8 </Router> 9 ); 10}
When defining routes, you can use the component prop to pass in your own components for rendering based on the route. This allows React Router to create a new element with React.createElement, but be cautious as it can lead to unmounting and remounting of components if not used correctly.
Understanding how routes work is essential. A route path is used to match URLs. For example:
1import { Route } from 'react-router-dom'; 2 3function App() { 4 return ( 5 <Router> 6 <Route path="/" component={Home} /> 7 </Router> 8 ); 9}
The Route component relies on the current URL to determine which UI to render based on whether the defined path matches the current URL.
In older versions of React Router, the Switch component was used to ensure that only the first matching route was rendered:
1import { Switch } from 'react-router-dom'; 2 3function App() { 4 return ( 5 <Router> 6 <Switch> 7 <Route path="/" component={Home} /> 8 <Route path="/about" component={About} /> 9 </Switch> 10 </Router> 11 ); 12}
Using the same component as the child of multiple Route elements at the same component tree level preserves the component's state across route changes.
However, with the introduction of React Router v6, the Switch component has been replaced by Routes. Here’s how you can achieve similar functionality with Routes:
1import { Routes } from 'react-router-dom'; 2 3function App() { 4 return ( 5 <Router> 6 <Routes> 7 <Route path="/" element={<Home />} /> 8 <Route path="/about" element={<About />} /> 9 </Routes> 10 </Router> 11 ); 12}
React Router provides several props and hooks to access route information:
• match: Provides information about the matched route.
• location: Gives details about the current URL.
• history: Allows programmatic navigation. The history object plays a crucial role in managing session history and enabling users to navigate through a web application effectively.
For example, you can use the useParams hook to access URL parameters:
1import { useParams } from 'react-router-dom'; 2 3function BlogPost() { 4 const { id } = useParams(); 5 return <div>Blog Post {id}</div>; 6}
Additionally, the useHistory hook can be used to access query parameters in the URL, helping to understand the user's current position within the application.
Nested routes allow you to create complex UI structures by nesting routes inside each other:
1import { Routes, Route } from 'react-router-dom'; 2 3function App() { 4 return ( 5 <Router> 6 <Routes> 7 <Route path="/messages" element={<Messages />}> 8 <Route path=":id" element={<Chats />} /> 9 </Route> 10 </Routes> 11 </Router> 12 ); 13}
When using child routes, be aware that pathless routes and the children prop interact with the parent match object, which can lead to potential errors if not handled correctly.
Error handling is an essential aspect of routing in React applications. When a user navigates to a non-existent route, a 404 error should be displayed to inform them that the page they are looking for does not exist. React Router provides a straightforward way to handle such errors by using a catch-all route.
To implement error handling in routing, you can use the Switch component and add a Route component with a path of * to catch all unmatched routes. This route can then render a custom NotFound component.
1import React from 'react'; 2import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; 3import Home from './Home'; 4import About from './About'; 5import NotFound from './NotFound'; 6 7function App() { 8 return ( 9 <Router> 10 <Switch> 11 <Route exact path="/" component={Home} /> 12 <Route path="/about" component={About} /> 13 <Route path="*" component={NotFound} /> 14 </Switch> 15 </Router> 16 ); 17} 18 19export default App;
In the above example, the NotFound component will be rendered when a user navigates to a non-existent route. This ensures that users are provided with a clear message when they attempt to access an invalid URL.
Route transition animations can significantly enhance the user experience of your React application by providing smooth transitions between different views. React Router can be combined with animation libraries to achieve this effect.
To use route transition animations, you can wrap your routes with a Transition component and specify the animation duration and timing function:
1import React from 'react'; 2import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; 3import { Transition } from 'react-router-transition'; 4import Home from './Home'; 5import About from './About'; 6 7function App() { 8 return ( 9 <Router> 10 <Transition duration={500} timingFn="ease-in-out"> 11 <Switch> 12 <Route exact path="/" component={Home} /> 13 <Route path="/about" component={About} /> 14 </Switch> 15 </Transition> 16 </Router> 17 ); 18} 19 20export default App;
In this example, the route transitions will be animated with a duration of 500ms and a timing function of “ease-in-out”. This creates a more engaging and visually appealing navigation experience for users.
Testing routes is a crucial part of ensuring that your React application works as expected. React Router provides the MemoryRouter component, which allows you to test routes in isolation without needing a full browser environment.
To test routes, you can wrap your routes with the MemoryRouter component and specify the initial route:
1import React from 'react'; 2import { MemoryRouter } from 'react-router-dom'; 3import { render } from '@testing-library/react'; 4import App from './App'; 5 6test('renders home page', () => { 7 const { getByText } = render( 8 <MemoryRouter initialEntries={['/']}> 9 <App /> 10 </MemoryRouter> 11 ); 12 13 expect(getByText('Home')).toBeInTheDocument(); 14});
In the above example, the MemoryRouter component is used to test the home page route. This allows you to verify that the correct component is rendered for a given route, ensuring that your routing logic is functioning correctly.
Security is a critical aspect of routing in React applications. Here are some key security considerations to keep in mind when using React Router:
• Validate User Input: Always validate user input to prevent malicious data from being injected into your routes. This helps protect against common attacks such as SQL injection and cross-site scripting (XSS).
• Use Secure Protocols: Ensure that your application uses secure protocols like HTTPS to encrypt data transmitted between the client and server. This helps protect sensitive information from being intercepted by attackers.
• Implement Authentication and Authorization: Use authentication and authorization mechanisms to restrict access to sensitive routes. This ensures that only authorized users can access certain parts of your application.
• Use Secure Routing Libraries: Utilize secure routing libraries like React Router to prevent common routing vulnerabilities. React Router is a well-maintained library that follows best practices for security.
By following these security considerations, you can ensure that your React application is secure and protected against common routing vulnerabilities. This helps maintain the integrity and confidentiality of your application and its data.
• Using the exact prop ensures that a route only matches when the path is exact:
1<Route exact path="/" element={<Home />} />
• Code-splitting can be used to optimize route rendering by loading components only when needed:
1import React, { lazy, Suspense } from 'react'; 2 3const Home = lazy(() => import('./Home')); 4 5function App() { 6 return ( 7 <Router> 8 <Suspense fallback={<div>Loading...</div>}> 9 <Routes> 10 <Route path="/" element={<Home />} /> 11 </Routes> 12 </Suspense> 13 </Router> 14 ); 15}
React Switch Route used to be a key part of routing in React. Although the Switch component has been replaced by Routes in newer versions, knowing how it worked can make the transition smoother. Developers who apply advanced routing methods and best practices can create fast and easy-to-use applications. Keeping up with these changes helps improve the overall user experience.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.