Next.js 15+ da barcha funksiyalar - cookies, headers, redirect, notFound, useRouter, generateMetadata, generateStaticParams, fetch, cacheLife va boshqalar
Next.js App Router - Functions API
Next.js App Router da 30 dan ortiq maxsus funksiyalar mavjud. Bu maqolada ularni kategoriyalar bo'yicha misollar bilan tushuntiraman.
Funksiyalar xaritasi
┌─────────────────────────────────────────────────────────┐
│ NEXT.JS FUNCTIONS │
├──────────────────┬──────────────────┬───────────────────┤
│ SERVER │ NAVIGATION │ CLIENT HOOKS │
│ (Server only) │ (Server/Client) │ ('use client') │
├──────────────────┼──────────────────┼───────────────────┤
│ cookies() │ redirect() │ useRouter() │
│ headers() │ permanentRedirect│ usePathname() │
│ fetch() │ notFound() │ useSearchParams()│
│ connection() │ forbidden() │ useParams() │
│ │ unauthorized() │ useLinkStatus() │
├──────────────────┼──────────────────┼───────────────────┤
│ CACHING │ GENERATION │ SEGMENT HOOK │
├──────────────────┼──────────────────┼───────────────────┤
│ cacheLife() │ generateMetadata│ useSelectedLayout│
│ cacheTag() │ generateStatic │ Segment() │
│ revalidateTag() │ Params │ useSelectedLayout│
│ updateTag() │ generateViewport│ Segments() │
│ revalidatePath()│ generateSitemaps│ │
│ after() │ ImageResponse │ │
└──────────────────┴──────────────────┴───────────────────┘
1. cookies() - Cookie bilan ishlash
Import: next/headers | Ishlaydi: Server Component, Route Handler, Server Action
import { cookies } from 'next/headers';
Cookie o'qish (Server Component)
export default async function Page() {
const cookieStore = await cookies(); // await kerak!
// Bitta cookie olish
const theme = cookieStore.get('theme');
// { name: 'theme', value: 'dark' }
// Cookie borligini tekshirish
const hasToken = cookieStore.has('token'); // true/false
// Barcha cookie lar
const all = cookieStore.getAll();
// [{ name: 'theme', value: 'dark' }, ...]
return <p>Mavzu: {theme?.value}</p>;
}
Cookie yozish (Server Action / Route Handler)
// app/actions.ts
'use server';
import { cookies } from 'next/headers';
export async function setTheme(theme: string) {
const cookieStore = await cookies();
// Oddiy set
cookieStore.set('theme', theme);
// Options bilan
cookieStore.set('theme', theme, {
httpOnly: true, // JS dan o'qib bo'lmaydi
secure: true, // Faqat HTTPS
sameSite: 'lax', // CSRF himoya
maxAge: 60 * 60 * 24 * 7, // 7 kun
path: '/',
});
}
Cookie o'chirish
'use server';
import { cookies } from 'next/headers';
export async function logout() {
const cookieStore = await cookies();
// Usul 1: delete()
cookieStore.delete('session');
// Usul 2: bo'sh qiymat
cookieStore.set('session', '');
// Usul 3: maxAge = 0
cookieStore.set('session', '', { maxAge: 0 });
}
Cookie options to'liq ro'yxati
| Option | Turi | Tavsif |
|---|---|---|
name |
string |
Cookie nomi |
value |
string |
Cookie qiymati |
expires |
Date |
Aniq tugash sanasi |
maxAge |
number |
Umr davomiyligi (soniyalarda) |
domain |
string |
Qaysi domenda mavjud |
path |
string |
Qaysi yo'lda mavjud (default: /) |
secure |
boolean |
Faqat HTTPS |
httpOnly |
boolean |
Faqat HTTP (JS kirish yo'q) |
sameSite |
'lax' \ |
'strict' \ |
2. headers() - So'rov headerlari
Import: next/headers | Ishlaydi: Server Component | Faqat o'qish
import { headers } from 'next/headers';
export default async function Page() {
const headersList = await headers(); // await kerak!
const userAgent = headersList.get('user-agent');
const referer = headersList.get('referer');
const authorization = headersList.get('authorization');
const acceptLanguage = headersList.get('accept-language');
return <p>Brauzer: {userAgent}</p>;
}
Header ni boshqa so'rovga uzatish
import { headers } from 'next/headers';
export default async function Page() {
const authorization = (await headers()).get('authorization');
// Header ni API so'rovga uzatish
const res = await fetch('https://api.example.com/user', {
headers: { authorization: authorization! },
});
const user = await res.json();
return <h1>{user.name}</h1>;
}
Mavjud metodlar
| Metod | Qaytaradi | Tavsif |
|---|---|---|
get(name) |
`string \ | null` |
has(name) |
boolean |
Header borligini tekshirish |
entries() |
Iterator |
Barcha key/value juftliklari |
keys() |
Iterator |
Barcha header nomlari |
values() |
Iterator |
Barcha header qiymatlari |
forEach(fn) |
void |
Har bir header uchun funksiya |
Muhim:
headers()faqat o'qish uchun - header yozib bo'lmaydi. Header o'rnatish uchun Route Handler danew Response()ishlatang.
3. redirect() va permanentRedirect() - Yo'naltirish
Import: next/navigation
redirect() - Vaqtinchalik yo'naltirish (307)
import { redirect } from 'next/navigation';
export default async function Page({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const team = await fetchTeam(id);
if (!team) {
redirect('/login'); // return kerak EMAS
}
return <h1>{team.name}</h1>;
}
permanentRedirect() - Doimiy yo'naltirish (308)
import { permanentRedirect } from 'next/navigation';
export default async function Page() {
permanentRedirect('/new-page');
// Brauzer va qidiruv botlari eski URL ni eslab qoladi
}
Server Action dan redirect
// app/actions.ts
'use server';
import { redirect } from 'next/navigation';
export async function createPost(data: FormData) {
const post = await db.posts.create({
data: { title: data.get('title') as string },
});
redirect(`/blog/${post.slug}`); // 303 status
}
Farqlari
| Funksiya | HTTP Status | Qachon ishlatish |
|---|---|---|
redirect() |
307 (Server Action da 303) | Login kerak, resurs ko'chdi (vaqtinchalik) |
permanentRedirect() |
308 | URL butunlay o'zgardi (doimiy) |
Muhim qoidalar
-
redirect()return yozish shart emas - unevertipini qaytaradi - Server Action va Route Handler da try/catch ichida ishlatmang
- Event handler da ishlatmang -
useRouter().push()ishlatang -
Tashqi URL ga ham yo'naltirish mumkin:
redirect('https://google.com')
4. notFound() - 404 sahifa
Import: next/navigation | Route ga mos not-found.tsx renderlanadi
import { notFound } from 'next/navigation';
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = await getPost(slug);
if (!post) {
notFound(); // not-found.tsx renderlanadi, 404 status
}
return <h1>{post.title}</h1>;
}
5. forbidden() va unauthorized() (Experimental)
import { forbidden, unauthorized } from 'next/navigation';
export default async function AdminPage() {
const session = await verifySession();
if (!session) {
unauthorized(); // 401 + unauthorized.tsx
}
if (session.role !== 'ADMIN') {
forbidden(); // 403 + forbidden.tsx
}
return <div>Admin Panel</div>;
}
6. useRouter() - Client-side navigatsiya
Import: next/navigation | Ishlaydi: Client Component ('use client')
'use client';
import { useRouter } from 'next/navigation';
export default function Dashboard() {
const router = useRouter();
return (
<div>
{/* Sahifaga o'tish (tarixga qo'shiladi) */}
<button onClick={() => router.push('/settings')}>
Sozlamalar
</button>
{/* Sahifaga o'tish (tarix almashtiriladi) */}
<button onClick={() => router.replace('/login')}>
Login
</button>
{/* Joriy sahifani yangilash */}
<button onClick={() => router.refresh()}>
Yangilash
</button>
{/* Oldindan yuklash */}
<button onMouseEnter={() => router.prefetch('/heavy-page')}>
Og'ir sahifa (hover qilganda yuklanadi)
</button>
{/* Orqaga */}
<button onClick={() => router.back()}>
Orqaga
</button>
{/* Oldinga */}
<button onClick={() => router.forward()}>
Oldinga
</button>
</div>
);
}
Barcha metodlar
| Metod | Tavsif |
|---|---|
push(href, { scroll }) |
Sahifaga o'tish, tarixga qo'shish |
replace(href, { scroll }) |
Sahifaga o'tish, tarixni almashtirish |
refresh() |
Joriy sahifani serverdan yangilash |
prefetch(href) |
Sahifani oldindan yuklash |
back() |
Brauzer tarixida orqaga |
forward() |
Brauzer tarixida oldinga |
scroll parametri
// Sahifa yuqorisiga scroll qilmaydi (default: true)
router.push('/page', { scroll: false });
Xavfsizlik:
router.push()ga foydalanuvchi kiritgan URL ni tekshirmasdan bermang - XSS xavfi bor!
7. usePathname() - Joriy URL yo'li
'use client';
import { usePathname } from 'next/navigation';
export function Breadcrumbs() {
const pathname = usePathname();
// /blog/my-post
const segments = pathname.split('/').filter(Boolean);
// ['blog', 'my-post']
return (
<nav>
{segments.map((segment, i) => (
<span key={i}> / {segment}</span>
))}
</nav>
);
}
8. useSearchParams() - URL query parametrlari
'use client';
import { useSearchParams } from 'next/navigation';
export function SearchFilter() {
const searchParams = useSearchParams();
const query = searchParams.get('query'); // "hello"
const page = searchParams.get('page'); // "2"
const tags = searchParams.getAll('tag'); // ["react", "next"]
const hasSort = searchParams.has('sort'); // true/false
const allParams = searchParams.toString(); // "query=hello&page=2"
return <p>Qidiruv: {query}, Sahifa: {page}</p>;
}
Muhim:
useSearchParams()eng yaqin<Suspense>chegarasigacha client-side rendering ga o'tkazadi.
9. useParams() - Dinamik route parametrlari
'use client';
import { useParams } from 'next/navigation';
export function PostHeader() {
const params = useParams();
// { slug: 'my-post' } yoki { category: 'react', slug: 'hooks' }
return <h1>Post: {params.slug}</h1>;
}
| Route | URL | useParams() |
|---|---|---|
app/blog/[slug]/page.tsx |
/blog/hello |
{ slug: 'hello' } |
app/shop/[...slug]/page.tsx |
/shop/a/b |
{ slug: ['a', 'b'] } |
10. useSelectedLayoutSegment() - Aktiv segment
Layout da qaysi child segment aktiv ekanligini aniqlash:
'use client';
import { useSelectedLayoutSegment } from 'next/navigation';
import Link from 'next/link';
export function NavLink({
href,
children,
}: {
href: string;
children: React.ReactNode;
}) {
const segment = useSelectedLayoutSegment();
// /blog da → 'blog'
// /about da → 'about'
// / da → null
const isActive = href.includes(segment || '');
return (
<Link
href={href}
style={{ fontWeight: isActive ? 'bold' : 'normal' }}
>
{children}
</Link>
);
}
11. useLinkStatus() - Link holati
Navigatsiya jarayonida vizual feedback berish:
'use client';
import { useLinkStatus } from 'next/link';
export function LoadingIndicator() {
const { pending } = useLinkStatus();
return pending ? <span className="spinner" /> : null;
}
12. fetch() - Kengaytirilgan fetch
Next.js Web fetch() ni kengaytirgan - server tomonida caching va revalidation qo'shilgan:
export default async function Page() {
// Default - statik prerendering da keshlanadi
const data = await fetch('https://api.example.com/posts');
// Har safar yangi ma'lumot
const fresh = await fetch('https://api.example.com/posts', {
cache: 'no-store',
});
// 1 soat kesh
const cached = await fetch('https://api.example.com/posts', {
next: { revalidate: 3600 },
});
// Tag bilan kesh (revalidateTag bilan yangilash uchun)
const tagged = await fetch('https://api.example.com/posts', {
next: { tags: ['posts'] },
});
// Majburiy kesh
const forced = await fetch('https://api.example.com/posts', {
cache: 'force-cache',
});
}
cache qiymatlari
| Qiymat | Tavsif |
|---|---|
'auto' (default) |
Next.js o'zi aniqlaydi |
'no-store' |
Har safar serverdan yangi oladi |
'force-cache' |
Keshdan beradi, yo'q bo'lsa yuklab keshlaydi |
next.revalidate qiymatlari
| Qiymat | Tavsif |
|---|---|
false |
Cheksiz kesh |
0 |
Keshlamaslik |
60 |
60 soniyada bir yangilash |
13. generateStaticParams() - Statik sahifalar generatsiyasi
Build vaqtida dinamik route lar uchun sahifalar yaratish:
// app/blog/[slug]/page.tsx
// Build vaqtida qaysi sahifalar yaratilishini aniqlash
export async function generateStaticParams() {
const posts = await fetch('https://api.example.com/posts')
.then(res => res.json());
return posts.map(post => ({
slug: post.slug,
}));
// [{ slug: 'post-1' }, { slug: 'post-2' }, ...]
}
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
return <h1>{slug}</h1>;
}
Strategiyalar
// 1. Barcha sahifalarni build da yaratish
export async function generateStaticParams() {
const posts = await fetchAllPosts();
return posts.map(p => ({ slug: p.slug }));
}
// 2. Faqat mashhurlarini build da, qolganini runtime da
export async function generateStaticParams() {
const posts = await fetchPopularPosts();
return posts.slice(0, 10).map(p => ({ slug: p.slug }));
}
// 3. Hech birini build da yaratmaslik (hammasi runtime da)
export async function generateStaticParams() {
return [];
}
// 4. Generatsiya qilinmaganlarni 404 qilish
export const dynamicParams = false;
Ko'p darajali dinamik segmentlar
// app/products/[category]/layout.tsx
export async function generateStaticParams() {
return [
{ category: 'electronics' },
{ category: 'clothing' },
];
}
// app/products/[category]/[product]/page.tsx
export async function generateStaticParams({
params: { category },
}: {
params: { category: string };
}) {
// Har bir category uchun productlar
const products = await fetchProducts(category);
return products.map(p => ({ product: p.id }));
}
14. generateMetadata() - SEO Metadata
Statik metadata
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Blog',
description: 'Eng yaxshi blog postlar',
};
export default function Page() {
return <h1>Blog</h1>;
}
Dinamik metadata
import type { Metadata } from 'next';
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}): Promise<Metadata> {
const { slug } = await params;
const post = await getPost(slug);
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: [post.coverImage],
},
};
}
Title template
// app/layout.tsx - Root layout
export const metadata: Metadata = {
title: {
template: '%s | MySite', // %s → child title bilan almashadi
default: 'MySite', // Child title bo'lmasa
},
};
// app/about/page.tsx
export const metadata: Metadata = {
title: 'Biz haqimizda',
};
// Natija: <title>Biz haqimizda | MySite</title>
// app/blog/page.tsx
export const metadata: Metadata = {
title: {
absolute: 'Blog', // Template ni e'tiborsiz qoldiradi
},
};
// Natija: <title>Blog</title>
To'liq metadata misol
export const metadata: Metadata = {
// Asosiy
title: 'Next.js Blog',
description: 'React framework haqida blog',
keywords: ['Next.js', 'React', 'TypeScript'],
authors: [{ name: 'Mehmon', url: 'https://example.com' }],
// Base URL
metadataBase: new URL('https://example.com'),
// Open Graph (Telegram, Facebook)
openGraph: {
title: 'Next.js Blog',
description: 'React framework haqida blog',
url: 'https://example.com',
siteName: 'MySite',
locale: 'uz_UZ',
type: 'website',
images: [
{
url: '/og-image.png',
width: 1200,
height: 630,
alt: 'Blog rasmi',
},
],
},
// Twitter
twitter: {
card: 'summary_large_image',
title: 'Next.js Blog',
description: 'React framework haqida blog',
creator: '@mehmon',
images: ['/twitter-image.png'],
},
// Robots
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-image-preview': 'large',
},
},
// Alternates (til versiyalari)
alternates: {
canonical: '/',
languages: {
'uz-UZ': '/uz',
'en-US': '/en',
'ru-RU': '/ru',
},
},
// Verifikatsiya
verification: {
google: 'google-site-verification-code',
yandex: 'yandex-verification-code',
},
// Ikonkalar
icons: {
icon: '/favicon.ico',
apple: '/apple-icon.png',
},
// Manifest (PWA)
manifest: '/manifest.json',
};
Metadata birlashtirish qoidasi
app/layout.tsx (title: "MySite", openGraph: { title: "MySite", description: "..." })
│
└── app/blog/page.tsx (title: "Blog")
│
Natija:
title = "Blog" ← almashtrildi
openGraph.title = "MySite" ← meros qoldi (blog da openGraph yo'q)
openGraph.description = "..." ← meros qoldi
Qoida: Child segment da maydon belgilansa - almashtiriladi. Belgilanmasa - ota dan meros qoladi.
15. Caching funksiyalari
cacheLife() - Kesh muddati
import { cacheLife } from 'next/cache';
async function BlogPosts() {
'use cache';
cacheLife('hours'); // 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'max'
return await fetchPosts();
}
cacheTag() + revalidateTag() / updateTag()
import { cacheTag, revalidateTag, updateTag } from 'next/cache';
// Keshlash va tag qo'yish
async function getPosts() {
'use cache';
cacheTag('posts');
return await fetchPosts();
}
// Server Action - fonda yangilash
async function createPost(data: FormData) {
'use server';
await db.posts.create(data);
revalidateTag('posts'); // stale-while-revalidate
}
// Server Action - darhol yangilash
async function updateCart(itemId: string) {
'use server';
await db.cart.update(itemId);
updateTag('cart'); // darhol keshni tozalash
}
revalidatePath() - Yo'l bo'yicha yangilash
import { revalidatePath } from 'next/cache';
export async function createPost() {
'use server';
await db.posts.create(...);
revalidatePath('/blog'); // /blog sahifasini yangilash
}
after() - Javobdan keyin ishlatish
So'rov javob yuborilgandan keyin loglar yoki analytics yuborish:
import { after } from 'next/server';
export default async function Page() {
const data = await fetchData();
after(async () => {
// Javob yuborilgandan KEYIN ishlaydi
await analytics.track('page-view');
await logger.log('Page rendered');
});
return <div>{data}</div>;
}
16. connection() - So'rov vaqtiga kechirish
Komponentni so'rov vaqtida ishlashga majburlash:
import { connection } from 'next/server';
async function DynamicContent() {
await connection(); // Prerendering dan chiqish
const now = new Date().toISOString();
const uuid = crypto.randomUUID();
return <p>{now} - {uuid}</p>;
}
17. draftMode() - Qoralama rejim
CMS bilan integratsiya - chop etilmagan kontentni ko'rish:
import { draftMode } from 'next/headers';
export default async function Page() {
const { isEnabled } = await draftMode();
const posts = isEnabled
? await fetchDraftPosts() // Qoralama postlar
: await fetchPublishedPosts(); // Chop etilgan postlar
return <div>{/* ... */}</div>;
}
Xulosa jadvali
Server funksiyalari (Server Component da ishlatiladi)
| Funksiya | Vazifasi | Dinamik rendering ga o'tkazadimi? |
|---|---|---|
cookies() |
Cookie o'qish/yozish | Ha |
headers() |
So'rov headerlari | Ha |
connection() |
So'rov vaqtiga kechirish | Ha |
draftMode() |
Qoralama rejim | Ha |
after() |
Javobdan keyin kod ishlatish | Yo'q |
Navigatsiya funksiyalari (Server va Client da)
| Funksiya | Vazifasi | HTTP Status |
|---|---|---|
redirect() |
Vaqtinchalik yo'naltirish | 307 (SA: 303) |
permanentRedirect() |
Doimiy yo'naltirish | 308 |
notFound() |
404 sahifa | 404 |
forbidden() |
403 sahifa | 403 |
unauthorized() |
401 sahifa | 401 |
Client hooklar ('use client' da ishlatiladi)
| Hook | Vazifasi |
|---|---|
useRouter() |
Programmatik navigatsiya |
usePathname() |
Joriy URL yo'li |
useSearchParams() |
Query parametrlari |
useParams() |
Dinamik route parametrlari |
useLinkStatus() |
Link navigatsiya holati |
useSelectedLayoutSegment() |
Aktiv child segment |
Generatsiya funksiyalari
| Funksiya | Vazifasi |
|---|---|
generateMetadata() |
SEO metadata |
generateStaticParams() |
Statik sahifalar |
generateViewport() |
Viewport sozlamalari |
generateSitemaps() |
Sitemap generatsiyasi |
Keshlash funksiyalari
| Funksiya | Vazifasi |
|---|---|
cacheLife() |
Kesh muddati |
cacheTag() |
Kesh tegi |
revalidateTag() |
Fonda yangilash |
updateTag() |
Darhol yangilash |
revalidatePath() |
Yo'l bo'yicha yangilash |
Bu maqola Next.js 15+ rasmiy dokumentatsiyasi asosida yozilgan. Savollar yoki takliflar bo'lsa, kommentariyada yozing!
(https://matkarim.uz)
Top comments (0)