Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
LoginSign Up
menu
  1. Home
  2. /Web Development
  3. /React
  4. /Routes And Navigation
Your Progress0%
0 of 42 completed

React Topics

Getting Started

  • What is React?
  • React vs Vanilla JavaScript
  • Setting Up Your Environment
  • Your First React App

JSX Fundamentals

  • Introduction to JSX
  • JSX Expressions and Variables
  • Conditional Rendering
  • Lists and Keys
  • Styling in JSX

Components Basics

  • Function Components
  • Props
  • Children Prop
  • Props Destructuring
  • Component Composition

State Management

  • Introduction to State
  • useState Hook
  • State Updates and Re-renders
  • Multiple State Variables
  • State Best Practices

Events and Interactivity

  • Handling Events
  • Event Objects
  • Forms in React
  • Form Validation

Side Effects and Data

  • Introduction to useEffect
  • Data Fetching
  • Cleanup Functions
  • Dependency Arrays

Advanced Hooks

  • useRef Hook
  • useContext Hook
  • useMemo Hook
  • useCallback Hook

React Patterns

  • Custom Hooks
  • Higher-Order Components
  • Render Props Pattern

React Router

  • Introduction to React Router
  • Routes and Navigation
  • Dynamic Routes and Parameters

Best Practices

  • Component Organization
  • Performance Optimization
  • Error Handling
  • Testing React Components

Real World Project

  • Building a Complete App

Routes and Navigation

Configuring routes and navigating between pages

You've learned the basics of React Router - now let's dive deeper! You'll learn how to navigate programmatically (from JavaScript code), create nested routes for complex layouts, use index routes for defaults, and build sophisticated navigation patterns. These features let you build real-world applications with complex routing requirements. Let's level up your routing skills! 🎯

Programmatic Navigation

Sometimes you need to navigate from code (not from a link click):

The useNavigate Hook

use-navigate.jsx
import { useNavigate } from 'react-router-dom'

function LoginForm() {
  const navigate = useNavigate()
  const [email, setEmail] = React.useState('')
  const [password, setPassword] = React.useState('')
  
  const handleSubmit = async (e) => {
    e.preventDefault()
    
    try {
      await loginUser(email, password)
      // Navigate to dashboard after successful login
      navigate('/dashboard')
    } catch (error) {
      console.error('Login failed:', error)
    }
  }
  
  return (
    <form onSubmit={handleSubmit}>
      <input 
        type="email" 
        value={email}
        onChange={e => setEmail(e.target.value)}
      />
      <input 
        type="password"
        value={password}
        onChange={e => setPassword(e.target.value)}
      />
      <button type="submit">Login</button>
    </form>
  )
}

// Common use cases for programmatic navigation:
// - After form submission
// - After successful authentication
// - Redirecting after timeout
// - Based on user role/permissions
// - After data is saved

Navigate with Options

navigate-options.jsx
import { useNavigate } from 'react-router-dom'

function Component() {
  const navigate = useNavigate()
  
  // Basic navigation
  navigate('/about')
  
  // Navigate with replace (doesn't add to history)
  navigate('/login', { replace: true })
  // User can't go "back" to previous page
  
  // Navigate with state (pass data to next page)
  navigate('/profile', { 
    state: { from: 'dashboard', userId: 123 } 
  })
  
  // Navigate back
  navigate(-1)  // Go back one page
  navigate(-2)  // Go back two pages
  
  // Navigate forward
  navigate(1)   // Go forward one page
  
  return <button onClick={() => navigate('/home')}>Go Home</button>
}

// Options explained:
// replace: true - Replaces current entry in history (can't go back)
// state: { ... } - Pass data to the destination route

useNavigate vs Link:

Use Link when:
• User clicks to navigate
• Navigation is the primary action
• You want a link (a tag) in HTML

Use useNavigate when:
• Navigation happens after logic (form submit, API call)
• Conditional navigation
• Programmatic redirects
• Need to navigate from event handlers

Nested Routes

Nested routes let you build layouts with sections that change while keeping other parts the same:

Basic Nested Routes

nested-basic.jsx
import { Routes, Route, Outlet, Link } from 'react-router-dom'

// Layout component with nested routes
function Dashboard() {
  return (
    <div className="dashboard">
      <h1>Dashboard</h1>
      <nav>
        <Link to="/dashboard/profile">Profile</Link>
        <Link to="/dashboard/settings">Settings</Link>
        <Link to="/dashboard/stats">Stats</Link>
      </nav>
      
      {/* Outlet renders the matched child route */}
      <div className="dashboard-content">
        <Outlet />
      </div>
    </div>
  )
}

function Profile() {
  return <div>Profile Content</div>
}

function Settings() {
  return <div>Settings Content</div>
}

function Stats() {
  return <div>Stats Content</div>
}

// Route configuration
function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      
      {/* Parent route */}
      <Route path="/dashboard" element={<Dashboard />}>
        {/* Child routes */}
        <Route path="profile" element={<Profile />} />
        <Route path="settings" element={<Settings />} />
        <Route path="stats" element={<Stats />} />
      </Route>
    </Routes>
  )
}

// URLs:
// /dashboard           → Dashboard (no child)
// /dashboard/profile   → Dashboard + Profile
// /dashboard/settings  → Dashboard + Settings
// /dashboard/stats     → Dashboard + Stats

The Outlet Component

outlet-explained.jsx
import { Outlet } from 'react-router-dom'

function Layout() {
  return (
    <div>
      <header>Header (always visible)</header>
      
      {/* Child routes render here */}
      <main>
        <Outlet />
      </main>
      
      <footer>Footer (always visible)</footer>
    </div>
  )
}

// Outlet acts as a placeholder for child routes
// It's like {children} but for nested routes

// Example flow:
// URL: /dashboard/profile
// 1. Dashboard component renders
// 2. Dashboard's <Outlet /> is replaced with Profile component
// 3. Result: Dashboard wrapper + Profile content

Nested Routes with Shared Layout

shared-layout.jsx
import { Routes, Route, Outlet, NavLink } from 'react-router-dom'

// Shared layout for all dashboard pages
function DashboardLayout() {
  return (
    <div className="dashboard-layout">
      <aside className="sidebar">
        <h2>Dashboard</h2>
        <nav>
          <NavLink to="/dashboard">Overview</NavLink>
          <NavLink to="/dashboard/users">Users</NavLink>
          <NavLink to="/dashboard/products">Products</NavLink>
          <NavLink to="/dashboard/orders">Orders</NavLink>
        </nav>
      </aside>
      
      <main className="dashboard-main">
        {/* Different pages render here */}
        <Outlet />
      </main>
    </div>
  )
}

// Page components
function Overview() {
  return <h1>Dashboard Overview</h1>
}

function Users() {
  return <h1>Users Management</h1>
}

function Products() {
  return <h1>Products List</h1>
}

function Orders() {
  return <h1>Orders History</h1>
}

// Routes configuration
function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      
      {/* Dashboard with nested routes */}
      <Route path="/dashboard" element={<DashboardLayout />}>
        <Route index element={<Overview />} />
        <Route path="users" element={<Users />} />
        <Route path="products" element={<Products />} />
        <Route path="orders" element={<Orders />} />
      </Route>
    </Routes>
  )
}

// Benefits:
// - Sidebar stays visible on all dashboard pages
// - Only main content changes
// - Navigation state preserved
// - Cleaner code organization

Index Routes

Index routes define the default child route when no child path is specified:

index-routes.jsx
import { Routes, Route, Outlet, Link } from 'react-router-dom'

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <nav>
        <Link to="/dashboard">Home</Link>
        <Link to="/dashboard/profile">Profile</Link>
        <Link to="/dashboard/settings">Settings</Link>
      </nav>
      <Outlet />
    </div>
  )
}

function DashboardHome() {
  return <div>Welcome to Dashboard Home!</div>
}

function App() {
  return (
    <Routes>
      <Route path="/dashboard" element={<Dashboard />}>
        {/* Index route - renders at /dashboard */}
        <Route index element={<DashboardHome />} />
        
        {/* Regular nested routes */}
        <Route path="profile" element={<Profile />} />
        <Route path="settings" element={<Settings />} />
      </Route>
    </Routes>
  )
}

// URLs:
// /dashboard          → Dashboard + DashboardHome (index route)
// /dashboard/profile  → Dashboard + Profile
// /dashboard/settings → Dashboard + Settings

// Without index route:
// /dashboard would show Dashboard but empty Outlet

// With index route:
// /dashboard shows Dashboard + DashboardHome (better UX!)

💡 Index Route Use Cases

Use index routes for:
• Default content in layouts
• Welcome/overview pages
• Empty state handling
• Dashboard home pages

Think of index routes as the "home page" of a section!

Route Matching and Priority

Route Order Matters (Sometimes)

route-order.jsx
// React Router v6 uses ranked route matching
// More specific routes match first, regardless of order!

function App() {
  return (
    <Routes>
      {/* These routes can be in any order */}
      <Route path="/users" element={<Users />} />
      <Route path="/users/:id" element={<UserDetail />} />
      <Route path="/users/new" element={<NewUser />} />
      <Route path="*" element={<NotFound />} />
    </Routes>
  )
}

// Matching logic:
// /users/new    → NewUser (most specific - exact match)
// /users/123    → UserDetail (dynamic parameter)
// /users        → Users (exact path)
// /anything     → NotFound (catch-all)

// React Router v6 automatically ranks routes by specificity:
// 1. Static paths (exact matches)
// 2. Dynamic segments (:id)
// 3. Catch-all routes (*)

Relative vs Absolute Paths

relative-paths.jsx
function App() {
  return (
    <Routes>
      <Route path="/dashboard" element={<Dashboard />}>
        {/* Relative paths (no leading slash) */}
        <Route path="profile" element={<Profile />} />
        {/* Matches: /dashboard/profile */}
        
        <Route path="settings" element={<Settings />} />
        {/* Matches: /dashboard/settings */}
        
        {/* Absolute path (with leading slash) */}
        <Route path="/admin" element={<Admin />} />
        {/* Matches: /admin (NOT /dashboard/admin) */}
      </Route>
    </Routes>
  )
}

// Rule:
// - Relative paths (no /) build on parent path
// - Absolute paths (with /) start from root

// In nested routes, usually use relative paths!

Interactive Demo

ReactPlayground.jsx
Code Editor
Preview

💡 Tip: Edit the code above and click "Run" to see your changes

Navigation with State

Pass data between routes using navigation state:

navigation-state.jsx
import { useNavigate, useLocation } from 'react-router-dom'

// Sending component
function UserList() {
  const navigate = useNavigate()
  
  const handleUserClick = (user) => {
    // Navigate with state
    navigate('/user-details', { 
      state: { 
        user: user,
        from: 'user-list' 
      } 
    })
  }
  
  return (
    <div>
      <button onClick={() => handleUserClick({ id: 1, name: 'Alice' })}>
        View Alice
      </button>
    </div>
  )
}

// Receiving component
function UserDetails() {
  const location = useLocation()
  
  // Access state from navigation
  const { user, from } = location.state || {}
  
  if (!user) {
    return <div>No user data</div>
  }
  
  return (
    <div>
      <h1>User Details</h1>
      <p>Name: {user.name}</p>
      <p>ID: {user.id}</p>
      <p>Came from: {from}</p>
    </div>
  )
}

// Use cases:
// - Pass form data between steps
// - Send selected item details
// - Track navigation history
// - Pass temporary data (not in URL)

Protected Routes Pattern

Redirect unauthorized users away from protected pages:

protected-routes.jsx
import { Navigate, useLocation } from 'react-router-dom'

// Protected Route component
function ProtectedRoute({ children }) {
  const { user } = useAuth()  // Your auth hook
  const location = useLocation()
  
  if (!user) {
    // Redirect to login, save where they were trying to go
    return <Navigate to="/login" state={{ from: location }} replace />
  }
  
  return children
}

// Usage in routes
function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/login" element={<Login />} />
      
      {/* Protected routes */}
      <Route
        path="/dashboard"
        element={
          <ProtectedRoute>
            <Dashboard />
          </ProtectedRoute>
        }
      />
      
      <Route
        path="/profile"
        element={
          <ProtectedRoute>
            <Profile />
          </ProtectedRoute>
        }
      />
    </Routes>
  )
}

// Login component can redirect back
function Login() {
  const navigate = useNavigate()
  const location = useLocation()
  
  const from = location.state?.from?.pathname || '/'
  
  const handleLogin = async (credentials) => {
    await loginUser(credentials)
    navigate(from, { replace: true })  // Go back to where they were
  }
  
  return <LoginForm onSubmit={handleLogin} />
}

Routes and Navigation Best Practices

  • Use nested routes for layouts - Keep common UI visible
  • Use index routes for defaults - Better UX
  • Use relative paths in nested routes - Easier to maintain
  • Use useNavigate for programmatic navigation - After actions
  • Use Link/NavLink for user clicks - Better accessibility
  • Add loading states - Show feedback during navigation
  • Handle 404s with catch-all route - path="*"
  • Use replace option carefully - Prevents going back
  • Protect private routes - Check authentication
  • Keep route structure logical - Match URL to app structure
  • Use navigation state sparingly - URL params are better for shareable data

Routing Architecture Tips:

Shallow nesting: Keep routes 2-3 levels deep maximum
Layouts: Use nested routes for shared layouts
Code splitting: Lazy load routes for better performance
SEO: Use meaningful URLs for better indexing
Analytics: Track route changes for user behavior

Key Takeaways

  • useNavigate enables programmatic navigation
  • Navigate with options: replace, state
  • Nested routes create layouts with <Outlet>
  • <Outlet> is a placeholder for child routes
  • Index routes provide default content
  • React Router v6 uses ranked route matching
  • Relative paths build on parent path
  • Absolute paths (with /) start from root
  • Pass data with navigation state
  • Access location state with useLocation
  • Protect routes with conditional rendering
  • Use <Navigate> for redirects
  • Nested routes keep common UI visible

What's Next?

You now understand advanced routing with React Router! You know how to navigate programmatically, create nested routes, and build complex layouts.

In the next lesson, you'll learn about Dynamic Routes and Parameters:

  • URL parameters with :id syntax
  • Accessing route parameters with useParams
  • Query strings and search params
  • Optional parameters
  • Building dynamic route structures

Get ready to build routes that handle dynamic data! 🚀

Learning advanced routing and navigation patterns in React Router!

Previous
Introduction to React Router
Next
Dynamic Routes and Parameters

Never Miss a New React Tutorial

Join 2,000+ developers learning React step-by-step. Get new tutorials, tips, and exclusive resources delivered to your inbox - completely FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

React Tutorials

0 of 42 completed

Your Progress0%

Topics

Getting Started

  • What is React?
  • React vs Vanilla JavaScript
  • Setting Up Your Environment
  • Your First React App

JSX Fundamentals

  • Introduction to JSX
  • JSX Expressions and Variables
  • Conditional Rendering
  • Lists and Keys
  • Styling in JSX

Components Basics

  • Function Components
  • Props
  • Children Prop
  • Props Destructuring
  • Component Composition

State Management

  • Introduction to State
  • useState Hook
  • State Updates and Re-renders
  • Multiple State Variables
  • State Best Practices

Events and Interactivity

  • Handling Events
  • Event Objects
  • Forms in React
  • Form Validation

Side Effects and Data

  • Introduction to useEffect
  • Data Fetching
  • Cleanup Functions
  • Dependency Arrays

Advanced Hooks

  • useRef Hook
  • useContext Hook
  • useMemo Hook
  • useCallback Hook

React Patterns

  • Custom Hooks
  • Higher-Order Components
  • Render Props Pattern

React Router

  • Introduction to React Router
  • Routes and Navigation
  • Dynamic Routes and Parameters

Best Practices

  • Component Organization
  • Performance Optimization
  • Error Handling
  • Testing React Components

Real World Project

  • Building a Complete App
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo