Link komponenti va useRouter — navigatsiya, prefetching

~15 daq · Next.js · Kirish va Asoslar

Muammodan boshlaylik

Siz Next.js da sahifalar orasida o'tish uchun oddiy <a> tegi ishlatdingiz:

<a href="/about">Biz haqimizda</a>

Ishlaydi. Lekin bir narsa sezasiz — har safar havola bosilganda sahifa to'liq qayta yuklanadi. Brauzer serverga yangi so'rov yuboradi, HTML keladi, sahifa yangilanadi. Xuddi oddiy veb sayt kabi.

Next.js ning asosiy afzalliklaridan biri — sahifalar orasida o'tish tez va silliq bo'lishi kerak. <a> tegi bu imkoniyatni yo'q qiladi.


Link komponenti

Next.js da sahifalar orasida o'tish uchun Link komponenti ishlatiladi:

import Link from 'next/link'

export default function Navbar() {
  return (
    <nav>
      <Link href="/">Bosh sahifa</Link>
      <Link href="/about">Biz haqimizda</Link>
      <Link href="/blog">Blog</Link>
    </nav>
  )
}

Ko'rinishda <a> tegi bilan bir xil. Lekin ichida butunlay boshqacha ishlaydi.

<a> va Link farqi

<a> bosilganda:

Brauzer → serverga so'rov → HTML keladi → sahifa to'liq yangilanadi

Link bosilganda:

Next.js → faqat yangi sahifaning ma'lumotini oladi → faqat kontent yangilanadi
(Navbar, Footer, Layout — qayta yuklanmaydi)

Natija — sahifalar orasida o'tish tez va silliq bo'ladi. Foydalanuvchi to'liq qayta yuklanishni sezmaydi.


Prefetching — eng kuchli xususiyat

Link ning eng muhim xususiyati — prefetching.

Tasavvur qiling: siz kitob o'qiyapsiz. Aqlli odam keyingi sahifani o'qib bo'lmasdan oldin uni ko'z yugurtiradi — shunda sahifa o'tkazganda hech narsa kutmaydi.

Link ham xuddi shunday ishlaydi. Foydalanuvchi havolaga hali bosmagan, lekin sichqonchani ustiga olib kelgan zahoti — Next.js orqa fonda o'sha sahifaning ma'lumotini yuklab olishni boshlaydi. Foydalanuvchi bosganida sahifa darhol ko'rinadi.

Bu production rejimida avtomatik ishlaydi. Development da ishlamaydi.

Prefetchingni o'chirish kerak bo'lsa:

<Link href="/heavy-page" prefetch={false}>
  Og'ir sahifa
</Link>

Dynamic URL

Ko'pincha URL da o'zgaruvchi qism bo'ladi — mahsulot ID si, blog slug i:

// Oddiy
<Link href={`/products/${product.id}`}>
  {product.name}
</Link>

// Ob'ekt ko'rinishida — murakkab URL lar uchun
<Link href={{
  pathname: '/products/[id]',
  query: { id: product.id },
}}>
  {product.name}
</Link>

Ikkalasi ham bir xil natija beradi. Birinchi usul odatda qisqaroq va o'qilishi oson.


useRouter — kod orqali navigatsiya

Link — foydalanuvchi bosganida o'tadi. Lekin ba'zan kod orqali o'tish kerak bo'ladi. Masalan:

  • Forma yuborilgandan keyin boshqa sahifaga o'tish
  • Login bo'lgandan keyin dashboard ga yo'naltirish
  • Tugma bosilganda boshqa sahifaga o'tish

Buning uchun useRouter hook ishlatiladi. Bu — Client Component da ishlaydi:

'use client'

import { useRouter } from 'next/navigation'

export default function LoginForm() {
  const router = useRouter()

  async function handleSubmit(e) {
    e.preventDefault()
    
    const res = await fetch('/api/login', { method: 'POST', ... })
    
    if (res.ok) {
      router.push('/dashboard')  // login bo'lgandan keyin dashboard ga
    }
  }

  return <form onSubmit={handleSubmit}>...</form>
}

router ning asosiy metodlari

router.push('/dashboard')      // yangi sahifaga o'tish (tarix saqlanadi)
router.replace('/dashboard')   // o'tish, lekin tarix saqlanmaydi
router.back()                  // oldingi sahifaga qaytish
router.refresh()               // hozirgi sahifani yangilash

push va replace farqi:

push — brauzer tarixiga qo'shadi. Foydalanuvchi "orqaga" tugmasini bossа — oldingi sahifaga qaytadi.

replace — tarixga qo'shmaydi. Masalan, login sahifasidan dashboard ga o'tganda replace ishlatiladi — foydalanuvchi "orqaga" bossa login sahifasiga qaytmasin.


usePathname va useSearchParams

Hozirgi URL ni bilish kerak bo'lganda — masalan, active link ni belgilash uchun:

'use client'

import Link from 'next/link'
import { usePathname } from 'next/navigation'

export default function Sidebar() {
  const pathname = usePathname()  // hozirgi URL: "/dashboard/users"

  const links = [
    { href: '/dashboard',         label: 'Asosiy' },
    { href: '/dashboard/users',   label: 'Foydalanuvchilar' },
    { href: '/dashboard/settings', label: 'Sozlamalar' },
  ]

  return (
    <nav>
      {links.map(link => (
        <Link
          key={link.href}
          href={link.href}
          style={{
            fontWeight: pathname === link.href ? 'bold' : 'normal',
            color: pathname === link.href ? 'blue' : 'black',
          }}
        >
          {link.label}
        </Link>
      ))}
    </nav>
  )
}

URL dagi ?search=hello kabi query parametrlarni olish uchun:

'use client'

import { useSearchParams } from 'next/navigation'

export default function SearchResults() {
  const searchParams = useSearchParams()
  const query = searchParams.get('q')  // ?q=javascript → "javascript"

  return <p>Qidiruv: {query}</p>
}

Server Component da navigatsiya

useRouter, usePathname, useSearchParams — bular faqat Client Component da ishlaydi. Server Component da URL ma'lumotlarini params va searchParams props orqali olasiz:

// Server Component — props orqali
export default async function Page({
  params,
  searchParams,
}: {
  params: { id: string }
  searchParams: { q?: string }
}) {
  const { id } = await params
  const query = searchParams.q

  return <div>ID: {id}, Qidiruv: {query}</div>
}

Tez-tez uchraydigan xatolar

1. next/router o'rniga next/navigation import qilish

// ❌ — Pages Router uchun, App Router da ishlamaydi
import { useRouter } from 'next/router'

// ✅ — App Router uchun
import { useRouter } from 'next/navigation'

Bu eng ko'p uchraydigan xato. Eski maqolalar va Stack Overflow javoblarida next/router ko'rasiz — App Router da bu ishlamaydi.

2. Server Component da useRouter ishlatish

// ❌ — Server Component da hook ishlamaydi
export default async function Page() {
  const router = useRouter()  // xato!
}

// ✅ — 'use client' qo'shing
'use client'
export default function Page() {
  const router = useRouter()
}

3. <a> tegi ishlatish

// ❌ — sahifa to'liq qayta yuklanadi
<a href="/about">Biz haqimizda</a>

// ✅
<Link href="/about">Biz haqimizda</Link>

Tashqi havolalar uchun (boshqa saytga) <a> to'g'ri — chunki u baribir tashqi saytga o'tadi.


Xulosa

Link — Next.js da ichki navigatsiya uchun. <a> o'rniga ishlatiladi. Sahifa to'liq qayta yuklanmaydi, prefetching avtomatik ishlaydi.

useRouter — kod orqali navigatsiya. Forma yuborilgandan keyin, login bo'lgandan keyin yo'naltirish uchun. Faqat Client Component da.

usePathname — hozirgi URL. Active link belgilash uchun. Faqat Client Component da.

useSearchParams — URL dagi ?key=value parametrlar. Faqat Client Component da.

Server Component da URL ma'lumotlari — params va searchParams props orqali.


Keyingi dars

7-dars: Image komponenti — optimizatsiya, lazy loading, placeholder

Oddiy <img> tegi bilan Next.js Image komponenti farqi va nima uchun Image ishlatish kerakligi.