Server vs Client Components & Router Hooks
Server vs Client Components & Router Hooks
1. Understanding Server vs. Client Components
Server Components (Default in Next.js):
Purpose: Render on the server side.
Usage: Ideal for data fetching, accessing backend resources (e.g., using an ORM), and rendering static content.
Limitations: Cannot use stateful or interactive hooks (like
useState
,useEffect, useParams, useRouter,
useSearchParams.) or browser-only APIs (e.g., localStorage, geolocation).
Client Components:
Purpose: Render on the client side.
Usage: Necessary when you need interactivity—such as event listeners, state management, or using browser APIs.
Declaration: Add
"
use client
"
at the top of your file to mark it as a client component.
Tip: Use server components when no interactivity is needed to reduce client-side JavaScript load, and switch to client components only when interactive behavior is required.
2. Converting a Component to a Client Component
a. Identify an Interactive Component
For example, imagine you have a page that needs to use router hooks or handle click events. This component should be converted to a client component.
b. Add the Client Directive
Open the file (e.g., a page inside
app/properties/[id]/page.jsx
).At the very top, add the following directive:
"use client";
Now you can use interactive hooks (like state hooks, effects, and router hooks).
Note: Without the
"use client"
directive, attempting to use hooks such asuseRouter
oruseState
will trigger an error, because these are only allowed in client components.
3. Introduction to Next.js Router Hooks
Next.js provides several router hooks under the next/navigation
module that let you handle routing dynamics efficiently. Here’s a quick overview:
a. useRouter
useRouter
Purpose: Enables you to navigate programmatically (e.g., redirecting users).
Usage Example:
import { useRouter } from 'next/navigation'; export default function MyComponent() { "use client"; // Required for client-side hooks const router = useRouter(); function goHome() { router.push('/'); } return ( <button onClick={goHome}> Go Home </button> ); }
b. useParams
useParams
Purpose: Retrieve dynamic route parameters (e.g.,
/properties/[id]
).Usage Example:
import { useParams } from 'next/navigation'; export default function PropertyPage() { "use client"; // Because we're accessing dynamic routing in a client context const { id } = useParams(); return ( <div> <h1>Property ID: {id}</h1> </div> ); }
c. useSearchParams
useSearchParams
Purpose: Access query parameters from the URL.
Usage Example:
import { useSearchParams } from 'next/navigation'; export default function SearchComponent() { "use client"; // Must be a client component const searchParams = useSearchParams(); const name = searchParams.get('name'); return ( <div> <p>Search parameter 'name' is: {name}</p> </div> ); }
d. usePathname
usePathname
Purpose: Obtain the current pathname from the URL.
Usage Example:
import { usePathname } from 'next/navigation'; export default function PathDisplay() { "use client"; const pathname = usePathname(); return ( <div> <p>Current Path: {pathname}</p> </div> ); }
4. Step-by-Step: Implementing Router Hooks in Your Application
Step 1: Create a New Client Component
File:
app/properties/[id]/page.jsx
Action: Add
"
use client
";
at the top.
Step 2: Use useRouter
for Navigation
useRouter
for NavigationImplementation:
"use client"; import { useRouter } from 'next/navigation'; export default function PropertyPage() { const router = useRouter(); function goToHome() { router.push('/'); } return ( <div> <h1>Property Details</h1> <button onClick={goToHome}>Go Home</button> </div> ); }
Step 3: Retrieve Dynamic Route Parameter with useParams
useParams
Implementation:
"use client"; import { useParams } from 'next/navigation'; export default function PropertyPage() { const { id } = useParams(); return ( <div> <h1>Property ID: {id}</h1> </div> ); }
Step 4: Use useSearchParams
to Get Query Parameters
useSearchParams
to Get Query ParametersImplementation:
"use client"; import { useSearchParams } from 'next/navigation'; export default function PropertyPage() { const searchParams = useSearchParams(); const ref = searchParams.get('ref'); return ( <div> <h1>Property Page</h1> {ref && <p>Referral Code: {ref}</p>} </div> ); }
Step 5: Display the Current Pathname with usePathname
usePathname
Implementation:
"use client"; import { usePathname } from 'next/navigation'; export default function PropertyPage() { const pathname = usePathname(); return ( <div> <p>Current URL: {pathname}</p> </div> ); }
5. Recap and Best Practices
Server Components vs. Client Components:
Use server components for static rendering and secure data fetching.
Use client components (with
"use client"
) when interactivity and stateful behavior are needed.
Router Hooks:
useRouter
for programmatic navigation.useParams
for dynamic route parameters.useSearchParams
for accessing query parameters.usePathname
for retrieving the current path.
Practical Tip: When designing components, decide whether they need to be interactive. If so, mark them as client components; otherwise, lean on server components to optimize performance and security.
Last updated