Next.js

Server and Client Components

by Tomas Trescak t.trescak@westernsydney.edu.au

Next.js

/

Server vs. Client Components

  • Fast page load : Server components render on server
  • Interactive elements : Client components handle user interactions
  • SEO friendly : Server components render initial content

Next.js

/

Server Components

  • Run on the server
  • Direct access to data sources
  • Faster initial load, better SEO
  • No interactivity

Next.js

/

Server Component / Example

    import { getRecentPosts } from '@/lib/api';

export default async function RecentPosts() {
  const posts = await getRecentPosts(); 

  return (
    <ul>
      {posts.map((post) => ( 
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}
  
/components/RecentPosts.tsx (Server Component)

Next.js

/

Client Components

  • Run in the browser
  • Handle user interactions
  • Manage state, update UI
  • Increased bundle, slower

Next.js

/

Client Component / Example

    'use client';

import { useState } from 'react';

export default function LikeButton({ postId }: { postId: string }) {
  const [liked, setLiked] = useState(false); 

  const handleLike = async () => { 
    // Logic to send like to the server
    setLiked(true); 
  };

  return (
    <button onClick={handleLike} disabled={liked}> 
      {liked ? 'Liked!' : 'Like'}
    </button>
  );
}
  
/components/LikeButton.tsx (Client Component)

Next.js

/

S & C: A Dynamic Duo (or Not?)

  • Server CAN render Client:
  • Client CANNOT render Server directly:
  • Passing Data

Next.js

/

Example: The Blog Post

    // Client Component
import LikeButton from '@/components/LikeButton'; 
// Could be Server or Client
import PostContent from '@/components/PostContent'; 

export default async function BlogPostPage(
  { params }: { params: { slug: string } }) 
{
  const post = await getPostData(params.slug); // Fetch on Server

  return (
    <div>
      {/* Data passed as prop */}
      <PostContent content={post.content} /> 
      {/* Data passed as prop */}
      <LikeButton postId={post.id} /> 
    </div>
  );
}
  
/pages/blog/[slug].tsx (Server Component)

Next.js

/

Example: The Blog Post

    // Client Component
import LikeButton from '@/components/LikeButton'; 
// Could be Server or Client
import PostContent from '@/components/PostContent'; 

export default async function BlogPostPage(
  { params }: { params: { slug: string } }) 
{
  const post = await getPostData(params.slug); // Fetch on Server

  return (
    <div>
      {/* Data passed as prop */}
      <PostContent content={post.content} /> 
      {/* ❌⚠️☢️ Will NOT WORK */}
      <LikeButton postId={post.id} onClick={() => {}} /> 
    </div>
  );
}
  
/pages/blog/[slug].tsx (Server Component)