Conditional Rendering Based on Pathname in Next.js: Deep Dive into useRouter and usePathname

Nov 20, 2025 · Programming · 18 views · 7.8

Keywords: Next.js | Pathname Conditional Rendering | useRouter Hook | usePathname | Client Components

Abstract: This article provides an in-depth exploration of implementing conditional rendering based on URL pathnames in Next.js applications, focusing on the implementation principles, use cases, and best practices of useRouter and usePathname methods. Through detailed code examples and comparative analysis, it demonstrates how to dynamically control Header display in layout components and address common requirements like hiding Headers on authentication pages. The article also discusses compatibility issues between Server Components and Client Components, and methods to avoid hydration mismatch errors.

Problem Background and Requirements Analysis

In Next.js application development, conditional rendering based on the current URL pathname is a frequent requirement. A typical scenario involves hiding Header components on authentication pages (such as login pages) while displaying them normally on other pages. This requirement stems from considerations for user experience optimization and interface logic separation.

From the problem description, developers need to obtain the current pathname in the MyApp component to decide whether to render the Header in the Layout component based on the pathname. This need is particularly common in Single Page Applications (SPAs) as they require dynamic handling of route changes on the client side.

Core Implementation of useRouter Hook

useRouter is a React Hook provided by Next.js specifically for accessing routing information in functional components. Its core functionality includes:

import { useRouter } from 'next/router'

export default function LayoutComponent() {
  const router = useRouter()
  
  // Get current pathname
  const currentPath = router.pathname
  
  // Conditional rendering logic
  const shouldShowHeader = currentPath !== '/signin'
  
  return (
    <div>
      {shouldShowHeader && <Header />}
      <main>
        {/* Page content */}
      </main>
    <div>
  )
}

In this implementation, useRouter() returns a router object where the pathname property provides the current page's pathname. By comparing the pathname with target paths (such as /signin), precise control over Header display logic can be achieved.

Difference Analysis Between pathname and asPath

Next.js router object provides two important path-related properties: pathname and asPath. Understanding their differences is crucial for correct implementation of conditional rendering.

import { useRouter } from 'next/router'

const ExampleComponent = () => {
  const { pathname, asPath } = useRouter()
  
  // Assuming current URL: /blog/hello-world
  console.log(pathname)  // Output: /blog/[slug]
  console.log(asPath)    // Output: /blog/hello-world
  
  return (
    <div>
      <p>Path Template: {pathname}</p>
      <p>Actual Path: {asPath}</p>
    </div>
  )
}

pathname reflects the filesystem path template, suitable for conditional judgments based on route structure; while asPath displays the actual path in the browser, appropriate for logic processing based on specific URL content.

Application of usePathname in App Router

With the introduction of App Router in Next.js 13, usePathname has become the recommended way to obtain pathnames. This is a Hook specifically designed for Client Components:

'use client'
import { usePathname } from 'next/navigation'

export default function AuthLayout() {
  const pathname = usePathname()
  
  // Hide Header on login pages
  const isAuthPage = pathname === '/signin' || pathname === '/signup'
  
  return (
    <div className="layout-container">
      {!isAuthPage && (
        <header className="main-header">
          <Navigation />
          <UserProfile />
        </header>
      )}
      <main className={isAuthPage ? 'auth-main' : 'normal-main'}>
        <Outlet />
      </main>
    </div>
  )
}

The design of usePathname considers the Server Components architecture. It is rendered as HTML during initial page load and doesn't require refetching during route navigation, providing better performance.

Traditional Usage of withRouter Higher-Order Component

For class components or scenarios requiring backward compatibility, the withRouter higher-order component provides another way to access routing information:

import { withRouter } from 'next/router'

class LayoutWithHeader extends React.Component {
  render() {
    const { router } = this.props
    const shouldShowHeader = router.pathname !== '/signin'
    
    return (
      <div>
        {shouldShowHeader && <Header />}
        <main>
          {this.props.children}
        </main>
      </div>
    )
  }
}

export default withRouter(LayoutWithHeader)

This method injects the router object through props, suitable for class component scenarios that don't support Hooks, but is gradually being replaced by Hooks in modern React development.

Performance Optimization and Best Practices

When implementing pathname-based conditional rendering, performance optimization and error handling should be considered:

'use client'
import { useEffect, useState } from 'react'
import { usePathname } from 'next/navigation'

export default function OptimizedLayout() {
  const pathname = usePathname()
  const [clientPathname, setClientPathname] = useState('')
  
  // Avoid hydration mismatch
  useEffect(() => {
    setClientPathname(pathname)
  }, [pathname])
  
  // Optimize frequent route changes with debouncing
  const [debouncedPath, setDebouncedPath] = useState('')
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedPath(clientPathname)
    }, 100)
    
    return () => clearTimeout(timer)
  }, [clientPathname])
  
  const shouldShowHeader = debouncedPath && !debouncedPath.startsWith('/auth')
  
  return (
    <div>
      {shouldShowHeader ? <Header /> : null}
      <main>
        {/* Page content */}
      </main>
    </div>
  )
}

Extended Practical Application Scenarios

Pathname-based conditional rendering can be extended to more complex scenarios:

import { useRouter } from 'next/router'

export default function AdvancedLayout() {
  const router = useRouter()
  const { pathname, query } = router
  
  // Multi-dimensional conditional judgments
  const isPublicPage = ['/', '/about', '/contact'].includes(pathname)
  const isAdminPage = pathname.startsWith('/admin')
  const hasModal = query.modal === 'true'
  
  return (
    <div>
      {!isPublicPage && <Header />}
      {isAdminPage && <AdminSidebar />}
      <main className={hasModal ? 'blur-background' : ''}>
        <PageContent />
      </main>
      {hasModal && <Modal />}
    </div>
  )
}

This pattern supports complex rendering logic based on various conditions including path prefixes, exact matches, and query parameters.

Compatibility Considerations and Migration Strategies

In projects mixing Pages Router and App Router, compatibility issues need attention:

Through appropriate selection and implementation, efficient and reliable pathname-based conditional rendering can be achieved in Next.js applications, enhancing user experience and code maintainability.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.