React Router is the de-facto standard for routing in React applications. Mastering it is essential for building single-page applications (SPAs) with proper navigation, URL management, and user experience. This comprehensive guide covers React Router from basics to advanced patterns, helping you build robust navigation systems.
What is React Router?
React Router enables client-side routing in React applications, allowing you to create single-page applications with multiple views and URLs without full page reloads. It keeps your UI in sync with the URL.
Why React Router?
React Router provides:
- Declarative routing
- URL-based navigation
- Nested routes
- Route protection
- Code splitting support
- Browser history management
Installation and Basic Setup
Start by installing React Router DOM (for web applications):
Basic Router Setup
Wrap your application with BrowserRouter and define routes:
Router Types
React Router provides different router types:
BrowserRouter- Uses HTML5 history API (recommended)HashRouter- Uses URL hash (for static hosting)MemoryRouter- For testing or non-browser environments
Basic Navigation
React Router provides several ways to navigate between routes.
Link Component
Use the Link component for declarative navigation:
NavLink Component
NavLink is like Link but adds active styling:
Programmatic Navigation
Use the useNavigate hook for programmatic navigation:
Dynamic Routes and URL Parameters
Dynamic routes allow you to create flexible URLs with parameters.
Route Parameters
Define dynamic segments in your routes:
Accessing Parameters
Use useParams hook to access route parameters:
Multiple Parameters
Routes can have multiple parameters:
Optional Parameters
Make parameters optional with the ? modifier:
Nested Routes
Nested routes create hierarchical route structures, perfect for layouts and dashboards.
Basic Nested Routes
Define nested routes using the Outlet component:
Nested Route Layouts
Create layout components for nested routes:
Index Routes
Use index routes for default child routes:
Query Parameters and Search Params
Handle URL query parameters for filtering, searching, and sharing state.
Reading Query Parameters
Use useSearchParams to read and update query parameters:
Updating Query Parameters
Update query parameters programmatically:
Multiple Query Parameters
Handle multiple query parameters:
Protected Routes and Authentication
Protect routes that require authentication or specific permissions.
Basic Protected Route
Create a component that checks authentication:
Protected Route with Redirect
Redirect unauthenticated users:
Role-Based Route Protection
Protect routes based on user roles:
Route Guards
Create reusable route guard components:
Route Loading and Code Splitting
Combine React Router with code splitting for optimal performance.
Lazy Loading Routes
Lazy load route components:
Loading States
Use Suspense for loading states:
Error Boundaries
Handle errors in route loading:
Advanced Routing Patterns
Route Configuration
Define routes in a configuration object for better organization:
Route Matching
Control how routes match URLs:
- Exact matching (default in v6)
- Wildcard routes
- Route priorities
Relative Routes
Use relative paths in nested routes:
Navigation Hooks
React Router provides several hooks for navigation and route information.
useNavigate
Programmatic navigation with options:
useLocation
Access current location information:
useParams
Access route parameters:
useSearchParams
Read and update query parameters:
useMatch
Check if current location matches a path:
Error Handling
Handle routing errors gracefully.
404 Not Found
Create a catch-all route for 404 pages:
Error Boundaries
Use Error Boundaries to catch route errors:
Route Transitions and Animations
Add smooth transitions between routes for better UX.
Basic Route Transitions
Use CSS transitions with route changes:
Advanced Animations
Use animation libraries like Framer Motion:
Best Practices
Follow these best practices for robust routing:
- Use absolute paths: More predictable and easier to refactor
- Implement 404 handling: Always have a catch-all route
- Protect sensitive routes: Never trust client-side protection alone
- Use route-based code splitting: Improve performance
- Keep routes organized: Use route configuration files
- Handle loading states: Always show feedback during navigation
- Use semantic URLs: Make URLs meaningful and shareable
- Test routes: Write tests for critical navigation flows
Common Patterns
Breadcrumbs
Implement breadcrumb navigation using useLocation and route configuration.
Active Link Highlighting
Use NavLink for automatic active state, or implement custom logic with useLocation.
Modal Routes
Create routes that render as modals while maintaining URL state.
Troubleshooting Common Issues
Routes Not Matching
Common causes:
- Incorrect path syntax
- Missing exact prop (v5) or incorrect matching
- Route order issues
Navigation Not Working
Check:
- Router is properly set up
- Links use correct paths
- No JavaScript errors
Query Parameters Not Updating
Ensure you're using setSearchParams correctly and not mutating the searchParams object directly.
Migration from v5 to v6
If migrating from React Router v5:
- Switch from Switch to Routes
- Update Route component syntax
- Replace useHistory with useNavigate
- Update redirects to use Navigate component
Conclusion
React Router provides powerful routing capabilities for React applications. Understanding its features—from basic navigation to advanced patterns like protected routes, nested routes, and code splitting—will help you build better navigation experiences. Start with the basics, gradually adopt advanced features, and always follow best practices. Remember: good routing improves both developer experience and user experience. With React Router, you can create intuitive, performant navigation that makes your single-page application feel like a native app.