Skip to content

Next.js Features#

Server Component (Default)#

async function Page() {
  const data = await fetch('https://api.example.com/data');
  const json = await data.json();

  return <div>{json.title}</div>;
}

Client Component#

'use client'

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

Dynamic Route#

// app/blog/[slug]/page.tsx
export default function Post({ params }: { params: { slug: string } }) {
  return <h1>Post: {params.slug}</h1>;
}

Server Action (Form)#

// app/actions.ts
'use server'

export async function createTodo(formData: FormData) {
  const title = formData.get('title');
  // Mutate data (e.g., db.insert)
}

// app/page.tsx
import { createTodo } from './actions'

export default function Page() {
  return (
    <form action={createTodo}>
      <input name="title" />
      <button type="submit">Add Todo</button>
    </form>
  )
}

Middleware (Route Guard)#

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/request';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token');

  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
}

export const config = {
  matcher: ['/dashboard/:path*', '/profile/:path*'],
};

Static Metadata#

import type { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Home Page',
  description: 'Welcome to my site',
};

Dynamic Metadata#

import type { Metadata } from 'next';

export async function generateMetadata({ params }): Promise<Metadata> {
  const product = await fetchProduct(params.id);
  return { title: product.name };
}

Image Optimization#

import Image from 'next/image';

<Image
  src="/hero.jpg"
  alt="Hero Image"
  width={800}
  height={600}
  priority
/>

Revalidate Data#

fetch('https://...', { next: { revalidate: 3600 } }); // 1 hour

Pathname & Params (Client)#

'use client'

import { usePathname, useSearchParams } from 'next/navigation';

function ClientInfo() {
  const pathname = usePathname();
  const searchParams = useSearchParams();
}