IlmHamroh
JavaScript Full-stack/23-qism. Next.js10/43-dars16 daqiqa
Mundarija (27)

Next.js Client Components: "use client" direktivasi va client chegarasi

Qisqacha: Fayl boshidagi "use client" qatori Next.js'ga aytadi: "bu fayl va u import qilgan hamma narsa brauzerga ham yuborilsin". Bunday Client Component ichida useState, useEffect, onClick va brauzer API'lari ishlaydi. Ikki muhim haqiqat: birinchisi — "use client" — client chegarasi, undan pastdagi har import brauzer to'plamiga qo'shiladi; ikkinchisi — client komponent ham birinchi ochilishda serverda HTML'ga chiziladi, brauzerda esa jonlanadi (hydration). Shuning uchun chizish paytida window ga tegib bo'lmaydi.

Bu darsda

  • "use client" qayerga va nima uchun yozilishini aniq bilasiz.
  • Import orqali tarqalishni o'lchangan raqam bilan ko'rasiz: bitta import — 13.3 KB.
  • Interaktivlikni "barg" komponentlarga ajratib, sahifani serverda qoldirasiz.
  • Client komponent ham serverda chizilishini va window is not defined xatosining sababini tushuntirasiz.
  • portfolio ga «Ulashish» tugmasini qo'shasiz.

Oldin bilishingiz kerak: Server Components, useEffect I, React'da hydration, Navigatsiya.

1. Nega bu kerak?

Server Components darsida post sahifasi serverda chizildi — marked brauzerga 0 bayt. Lekin sahifa ostida «Ulashish» tugmasi kerak. U:

  • bosilishni kutadi (onClick);
  • telefonda tizimning ulashish oynasini ochadi (navigator.share), kompyuterda havolani nusxalaydi (navigator.clipboard);
  • natija xabarini ko'rsatadi ("Havola nusxalandi") — demak holat (useState) bor.

Hammasi — brauzer narsalari. Server Component'da ularning birortasi yo'q. Bizga brauzerda ham ishlaydigan komponent kerak.

Butun sahifani "use client" qilish — eng oson, lekin eng yomon yo'l: unda marked, post matni va hamma narsa brauzerga ketadi. To'g'ri yo'l — faqat tugmaning o'zini client qilish. Sahifa — server, tugma — kichik "orol".

Hayotiy o'xshatish: muzey. Zallardagi suratlar — server komponentlar: qarab o'tasiz, ularni hech kim qo'lga bermaydi. Faqat ba'zi joylarda "tegish mumkin" degan interaktiv ekranlar bor — client komponentlar. Butun muzeyni interaktiv qilish shart emas.

2. "use client" — client chegarasi

2.1 Kanondagi UlashishTugmasi

tsx
"use client";

import { useState } from "react";

// Kichik client orol (N-10): brauzer API (navigator.share /
// clipboard) va holat kerak. Sahifaning qolgani — server.
export function UlashishTugmasi({ sarlavha }: { sarlavha: string }) {
  const [xabar, setXabar] = useState("");

  async function ulash() {
    const url = window.location.href;
    try {
      if (navigator.share) {
        await navigator.share({ title: sarlavha, url });
        return;
      }
      await navigator.clipboard.writeText(url);
      setXabar("Havola nusxalandi");
    } catch (xato) {
      // Foydalanuvchi oynani yopsa — AbortError, bu xato emas
      if (xato instanceof DOMException && xato.name === "AbortError") return;
      setXabar("Nusxalab bo'lmadi — manzil satridan oling");
    }
  }

  return (
    <>
      <button type="button" onClick={ulash}>
        Ulashish
      </button>{" "}
      <span role="status">{xabar}</span>
    </>
  );
}

Kanon izohi ikki qatorga bo'lindi; ikki kod qatori kanonda 70 belgidan uzun. Qatorma-qator:

Qism Nima qiladi
"use client" Faylning birinchi qatori, importlardan oldin
useState Natija xabari — brauzerdagi holat
window.location.href Joriy manzil — hodisa ichida, chizishda emas
navigator.share bormi? Bor bo'lsa — tizim oynasi; yo'q bo'lsa — nusxalash
AbortError Foydalanuvchi oynani yopdi — xato emas, jim
role="status" Ekran o'quvchi "Havola nusxalandi" ni o'qiydi

navigator.share — Web Share API: telefonda Telegram, WhatsApp kabi ilovalar ro'yxatini ochadi. Hamma brauzerda yo'q, shuning uchun avval tekshiriladi — xususiyatni aniqlash (feature detection).

2.2 Client chegarasi nimani anglatadi?

"use client" — "bu komponent faqat brauzerda" degani emas. U modul darajasidagi client chegarasi: shu fayldan boshlab pastga qarab hamma import client to'plamiga qo'shiladi. Uni Maxsus fayllar darsidagi xato chegarasi (error boundary) bilan adashtirmang: xato chegarasi xatoni ushlaydi, client chegarasi esa kod qayerga borishini belgilaydi.

flowchart TB
  P["post/page.tsx<br/>server"] --> M["blog.ts — marked<br/>server"]
  P --> U["UlashishTugmasi.tsx<br/>'use client' — client chegarasi"]
  U --> R["react: useState<br/>client to'plamida"]
  U -.->|agar import qilsa| X["sana.ts, marked…<br/>ular ham client"]

Server sahifa client komponentni import qila oladi — bu client chegarasidan o'tish. Client komponent import qilgan narsa esa (react, yordamchi funksiyalar, kutubxonalar) brauzerga ketadi. Client chegarasining o'zi — "use client" yozilgan fayl.

Natija: "use client" faqat client chegarasi fayllarida kerak. UlashishTugmasi ichida boshqa client komponent ishlatilsa, unga yana "use client" yozish shart emas — u allaqachon client chegarasining ichida.

2.3 Biz o'lchadik: bitta import — 13.3 KB

Tarqalishni o'z ko'zimiz bilan ko'rish uchun tajriba qildik: marked ni client komponentda ishlatdik.

tsx
"use client";

import { marked } from "marked";

export function MarkdownMijoz({ matn }: { matn: string }) {
  const html = marked.parse(matn, { async: false });
  return <div dangerouslySetInnerHTML={{ __html: html }} />;
}

next build dan keyin .next/static/chunks/ da marked kodi bor faylni qidirdik:

text
0rl1sk8_ft0yq.js xom 45714 gzip 13593

Bitta fayl, 45.7 KB xom, 13.3 KB gzip — butun marked kutubxonasi brauzerga ketdi. Kanondagi blog'da (marked faqat blog.ts da, server tomonda) bu bo'lak umuman yo'q edi.

Bitta import qatori 13 KB qo'shdi. Yon tomondagi ta'sirni ham unutmang: bu 13 KB sahifani har ochgan foydalanuvchi uchun, telefon va sekin internetda ham.

Tekshirib ko'ring: sana.ts dagi oyniYoz funksiyasi server komponentlarda ham, UlashishTugmasi da ham ishlatilsa — u brauzer to'plamiga tushadimi?

Javob

Ha. Client komponent import qilgani uchun sana.ts client to'plamiga ham qo'shiladi (server tomonda esa alohida ishlatilaveradi). Modul ikki tomonda ham bo'lishi mumkin — bu xato emas, faqat hajm. Funksiya kichik bo'lsa, muammo yo'q; katta kutubxona bo'lsa — o'ylab ko'ring.

3. Client komponent ham serverda chiziladi

3.1 Biz tekshirdik: HTML'da tugma bor

Ko'p dasturchilar adashadigan joy: "client komponent — faqat brauzerda chiziladi". Tekshiramiz. Holat 11 ni next build + next start qilib, post sahifasini curl bilan so'radik — JS bajarilmaydi, faqat server qaytargan HTML:

text
HTML: 12685 bayt; Ulashish tugmasi HTML'da: 1

<button type="button">Ulashish</button> — server HTML'ining ichida. Ya'ni Next.js UlashishTugmasi ni serverda ham chaqirdi: useState("") boshlang'ich qiymat bilan, tugmani chizdi. Brauzerga kelgach React o'sha HTML'ni oladi va unga onClick ni "ulaydi" — hydration (jonlantirish). SPA uchun SEO darsida prerender bilan ko'rgandingiz; chuqur — Hydration darsida.

Server Component Client Component
Serverda chiziladimi Ha Ha (birinchi ochilish)
Brauzerda chiziladimi Yo'q Ha (hydration va keyingi o'zgarishlar)
JS kodi brauzerga Yo'q Ha
Hook'lar, hodisalar Yo'q Ha

3.2 Biz sinadik: window is not defined

Demak client komponentning chizish qismi serverda ham bajariladi — u yerda window yo'q. Tajriba: joriy manzilni chizishda o'qiydigan komponent.

tsx
"use client";

export function Manzil() {
  return <p>Manzil: {window.location.href}</p>;
}

Build:

text
Error occurred prerendering page "/sinov9". Read more: https://nextjs.org/docs/messages/prerender-error
ReferenceError: window is not defined
    at <unknown> (src\komponentlar\Manzil.tsx:4:22)

"window aniqlanmagan" — Node'da window degan global yo'q. "use client" bu yerda yordam bermadi: komponent baribir serverda chizildi.

UlashishTugmasi da nega bunday xato yo'q? Chunki window.location.href hodisa ichida — ulash() faqat bosilganda, brauzerda ishlaydi. Qoida:

Qayerda window, localStorage, navigator
Komponent tanasi (chizish) Yo'q — serverda ham bajariladi
Hodisa ishlovchisi (onClick) Ha — faqat brauzerda
useEffect ichida Ha — faqat brauzerda, chizilgandan keyin

Brauzer qiymatini ekranda ko'rsatish kerak bo'lsa (manzil, ekran kengligi, saqlangan tema) — boshida server bilan bir xil qiymat, keyin effektda yoki useSyncExternalStore bilan almashtirish. Bu — Hydration darsining mavzusi.

4. Barglarni client qiling

4.1 Qoida

Komponentlar daraxtini tasavvur qiling: tepada sahifa, pastda kichik elementlar. Barg (leaf) — eng pastdagi, boshqa komponentni o'z ichiga olmaydigan komponent. Qoida: "use client" ni iloji boricha barglarga qo'ying.

portfolio kanonida holat 11 gacha to'rtta client komponent bor — hammasi barg:

Komponent Nega client Qayerda
NavHavola usePathname Menyu
OrqagaTugmasi router.back() 404 sahifasi
TegFiltri useSearchParams Loyihalar
UlashishTugmasi useState, navigator Post

Qolgan hammasi — sahifalar, layout, kartalar, footer — server. Brauzer JS'i shuning uchun kam o'sdi: holat 04 (client komponentsiz) 135.4 KB → holat 06 (3 ta) 137.4 KB → holat 11 (4 ta) 138.6 KB. To'rtta orol — jami ~3 KB.

4.2 Natija oynasida: barg komponent

Natija oynasi — brauzer, unda har komponent client. Lekin barg g'oyasini ko'rish mumkin: PostPage — "server" qismi (hech qanday hook'siz), ShareButton — kichik client orol. Brauzer API o'rniga share funksiyasini prop bilan beramiz: natija oynasida navigator.share brauzerga qarab bor yoki yo'q, natija bir xil bo'lmasdi. Funksiya foydalanuvchi oynani yopganini taqlid qiladi (AbortError), ikkinchi safar — muvaffaqiyat.

tsx
import { useState } from "react";

let calls = 0;
async function fakeShare(): Promise<void> {
  calls++;
  if (calls === 1) throw new DOMException("yopildi", "AbortError");
}

function ShareButton({ share }: { share: () => Promise<void> }) {
  const [message, setMessage] = useState("");
  async function handleClick() {
    try {
      await share();
      setMessage("Ulashildi");
    } catch (error) {
      const aborted =
        error instanceof DOMException && error.name === "AbortError";
      if (aborted) {
        console.log("foydalanuvchi oynani yopdi — jim");
        return;
      }
      setMessage("Ulashib bo'lmadi");
    }
  }
  return (
    <>
      <button onClick={handleClick}>Ulashish</button>{" "}
      <span role="status">{message}</span>
    </>
  );
}

// "server" qismi — hook yo'q, faqat chizadi
function PostPage() {
  console.log("PostPage chizildi");
  return (
    <article>
      <h1>Server Components</h1>
      <ShareButton share={fakeShare} />
    </article>
  );
}

export default function App() {
  return <PostPage />;
}

Konsolda:

text
PostPage chizildi
foydalanuvchi oynani yopdi — jim

Ekranda:

text
Server Components
Ulashish Ulashildi

"PostPage chizildi" — bir marta. Tugma ikki marta bosildi, holat o'zgardi, lekin faqat ShareButton qayta chizildi. Haqiqiy Next.js'da bundan ham kuchli: PostPage brauzerda umuman chizilmaydi, uning kodi brauzerga kelmaydi.

E'tibor bering: share={fakeShare} — funksiya prop. Natija oynasida bu ishlaydi, chunki hammasi brauzerda. Haqiqiy server sahifasidan client komponentga funksiya uzatib bo'lmaydi — Kompozitsiya darsida haqiqiy xato bilan ko'ramiz.

4.3 Tepani client qilish narxi

Teskari holatni ko'ring: "use client" ni post/page.tsx ga yozsak, nima bo'ladi?

  • async sahifa ishlamay qoladi — client komponent async bo'la olmaydi.
  • blog.ts ni import qilib bo'lmaydi — server-only buni to'xtatadi (pastda xato).
  • Hatto shu to'siqlar bo'lmasa ham — marked (13.3 KB) va butun daraxt brauzerga ketadi.

Tepadagi bitta "use client" — butun daraxtni client qiladi. Pastdagi bitta "use client" — faqat bargni.

5. Client chegarasini buzish: server-only

5.1 Kanon tajribasi

blog.ts ning birinchi qatori — import "server-only". Bu kichik paket (server-only 0.0.1) bitta ish qiladi: modul client to'plamiga tushsa, build'ni to'xtatadi. Kanon ataylab blog.ts ni client komponentga import qildi. Build — 5 ta xato (asosiy qatorlar):

text
Error: It is not allowed to define inline "use cache" annotated functions in Client Components.
Error: It is not allowed to define inline "use cache" annotated functions in Client Components.
Error: You're importing a module that depends on "cacheLife". This API is only available in Server Components in the App Router, but you are using it in the Pages Router.
Error: You're importing a module that depends on "server-only". This API is only available in Server Components in the App Router, but you are using it in the Pages Router.
Error: 'server-only' cannot be imported from a Client Component module

Oxirgisi — asosiysi: "'server-only' ni Client Component modulidan import qilib bo'lmaydi". Uchinchi va to'rtinchi xabar chalg'ituvchi: "siz uni Pages Router'da ishlatyapsiz" deydi, holbuki loyihada pages/ yo'q. Next.js client modulni "server emas" deb umumlashtiradi, xabar matni esa eski davrdan qolgan. Saboq: xatolar ro'yxatida eng aniq qatorni qidiring.

Xabar bilan birga import izi (import trace) ham chiqadi — qaysi fayl qaysi faylni chaqirib, client chegarasini buzganini ko'rsatadi:

text
Client Component Browser:
  ./src/malumot/blog.ts [Client Component Browser]
  ./src/komponentlar/Sinov.tsx [Client Component Browser]
  ./src/komponentlar/Sinov.tsx [Server Component]
  ./src/app/(sayt)/blog/[slug]/page.tsx [Server Component]

Pastdan o'qing: sahifa (server) → Sinov.tsx (client chegarasi) → blog.ts (client to'plamiga tushib qoldi).

5.2 server-only va client-only

Paket Nima qiladi Qayerda
server-only Client to'plamiga tushsa — build xatosi Sirlar, fs, baza bilan ishlaydigan fayllar
client-only Server tomonda import qilinsa — build xatosi Faqat brauzerda ma'noli kod (window bilan ishlovchi)

server-only — arzon sug'urta: sir saqlaydigan har modulning birinchi qatori. Bir kun kimdir uni xato bilan client komponentga import qilsa, sir brauzerga emas, build xatosiga chiqadi.

6. "use client" qoidalari

Qoida Izoh
Faylning eng boshida Importlardan oldin; izohlar oldida bo'lishi mumkin
Qo'shtirnoq bilan, nuqta-vergulsiz ham bo'ladi "use client" yoki 'use client'
Faqat client chegarasi fayllarida Ichkaridagilar avtomatik client
Props — seriyalanadigan Server'dan keladigan props matnga aylanadi (Kompozitsiya)
async komponent emas Client komponent async function bo'la olmaydi
"use server" bilan adashtirmang U — Server Action belgisi (Server Actions I)

Tekshirib ko'ring: "use client" ni import qatorlaridan keyin yozdingiz. Nima bo'ladi?

Javob

Direktiva sifatida ishlamaydi: JS'da "use client" oddiy satr ifodasi, uni faqat fayl (yoki funksiya) boshida direktiva deb o'qiladi — "use strict" kabi. Next.js faylni server komponent deb oladi va hook'lar uchun "depends on useState" xatosini beradi.

7. Portfolio qadami: «Ulashish» tugmasi (2-qism)

Server Components darsidagi blogga:

Fayl Nima
komponentlar/UlashishTugmasi.tsx Client: navigator.share → clipboard → role="status"
blog/[slug]/page.tsx Post ostida <UlashishTugmasi sarlavha={p.sarlavha} />

Kanon o'lchovi: /blog/server-components — 138.6 KB, boshqa sahifalar 137.9 KB: tugma +0.7 KB. marked brauzerga 0 bayt. Commit hali qilmang — keyingi darsda.

Tekshirish: telefonda (yoki Chrome DevTools'ning qurilma rejimida) tugma tizim oynasini ochishi, kompyuterda "Havola nusxalandi" yozishi kerak. Oynani yopsangiz — hech qanday xabar chiqmasligi kerak (AbortError).

8. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
ReferenceError: window is not defined Client komponent chizishida brauzer API Hodisa yoki useEffect ichiga
Sahifa JS'i keskin oshdi Katta kutubxona client komponentda Ishni serverga, client'ga faqat natija
'server-only' cannot be imported from a Client Component module Server moduli client chegarasidan o'tdi Ma'lumotni server sahifada oling, prop bilan bering
"… but you are using it in the Pages Router" Chalg'ituvchi matn — aslida client modul Import izini pastdan o'qing
"use client" ishlamaydi Importlardan keyin yozilgan Fayl boshiga
Hamma narsa "use client" Har faylga yozilgan Faqat client chegarasi — barg komponentlar
async client komponent xatosi Client'da async function Ma'lumotni serverda oling yoki use()

9. Mashqlar

Mashqlar kurs/mashqlar/23/10-client-components/ da.

1-mashq (oson): qaysi fayl client?

Daraxt: page.tsx → Karta.tsx → LayklarTugmasi.tsx (useState) va Narx.tsx (oddiy matn). Qaysi faylga "use client" kerak?

  • page.tsx —
  • Karta.tsx —
  • LayklarTugmasi.tsx —
  • Narx.tsx —
Yechim

Faqat LayklarTugmasi.tsx — u holat ishlatadigan barg. Qolganlari server: Karta va page faqat chizadi, Narx matn. "use client" ni Karta ga yozsangiz ham ishlaydi, lekin Karta va Narx kodi ham brauzerga ketadi — keraksiz.

2-mashq (o'rta): client chegarasi qayerda?

Funksiya yozing: clientModules(graph, entry) — modullar grafi ({ "page.tsx": { client: false, imports: [...] }, … }) va kirish faylini oladi, client to'plamiga tushadigan modullar ro'yxatini qaytaradi. Qoida: client: true modul va uning hamma importlari (chuqur) — client; server moduldan client modulga o'tish — client chegarasi. Natija alifbo tartibida. Ishora: rekursiv yurish va Set (Set).

Yechim
js
function clientModules(graph, entry) {
  const result = new Set();
  function visit(name, insideClient) {
    const mod = graph[name];
    const isClient = insideClient || mod.client;
    if (isClient) {
      if (result.has(name)) return;
      result.add(name);
    }
    for (const dep of mod.imports) visit(dep, isClient);
  }
  visit(entry, false);
  return [...result].sort();
}

const graph = {
  "page.tsx": { client: false, imports: ["blog.ts", "Ulashish.tsx"] },
  "blog.ts": { client: false, imports: ["marked"] },
  marked: { client: false, imports: [] },
  "Ulashish.tsx": { client: true, imports: ["react", "sana.ts"] },
  react: { client: false, imports: [] },
  "sana.ts": { client: false, imports: [] },
};

console.log(clientModules(graph, "page.tsx"));

Konsolda:

text
[ 'Ulashish.tsx', 'react', 'sana.ts' ]

marked ro'yxatda yo'q: unga faqat server moduli (blog.ts) yetadi. sana.ts va react esa bor — ularni client chegarasi fayli import qilgan. client: false bo'lsa ham, client chegarasining ichida bo'lgani yetarli. Haqiqiy bundler (Turbopack) ham shunday yuradi, faqat minglab modul bilan.

3-mashq (qiyin): ekran kengligi — xavfsiz usulda

Komponent yozing: WidthBadge — ekran kengligini ko'rsatadi: Keng: 1280px. Talab: serverda ham xatosiz chizilsin, ya'ni chizishda window yo'q. Boshlang'ich holat — "Keng: …", effekt ichida haqiqiy qiymat. Natija oynasida o'lcham har xil bo'lgani uchun, kenglikni getWidth prop bilan bering (sinovda () => 1280). Konsolga har chizishni yozing.

Yechim
tsx
import { useEffect, useState } from "react";

function WidthBadge({ getWidth }: { getWidth: () => number }) {
  const [width, setWidth] = useState<number | null>(null);
  useEffect(() => {
    setWidth(getWidth()); // faqat brauzerda, chizilgandan keyin
  }, [getWidth]);
  console.log("chizildi:", width);
  return <p>Keng: {width === null ? "…" : `${width}px`}</p>;
}

// haqiqiy kodda: () => window.innerWidth
const fixedWidth = () => 1280;

export default function App() {
  return <WidthBadge getWidth={fixedWidth} />;
}

Konsolda:

text
chizildi: null
chizildi: 1280

Ekranda:

text
Keng: 1280px

Birinchi chizish (null, "…") — serverda ham aynan shunday bo'ladi, shuning uchun HTML va brauzerdagi birinchi chizish bir xil — Hydration xatosi yo'q. Effekt faqat brauzerda ishlaydi va haqiqiy qiymatni qo'yadi. fixedWidth komponentdan tashqarida e'lon qilingan: ichkarida bo'lsa, har chizishda yangi funksiya bo'lib, effekt qayta-qayta ishlardi (useEffect II).

4-mashq: Portfolio qadami

UlashishTugmasi ni yozing va post sahifasiga qo'shing. Tekshiring: curl http://localhost:3000/blog/<slug> chiqishida Ulashish tugmasi bormi (serverda chizilgani)? DevTools Network'da sahifa JS'i boshqa sahifalardan ~1 KB dan ko'p oshmasligi kerak.

Yechim

Namuna — «"use client" — client chegarasi» bo'limidagi kanon kodi. curl chiqishida <button type="button">Ulashish</button> bo'lishi kerak — client komponent ham serverda chiziladi. JS sezilarli oshsa — UlashishTugmasi katta narsa import qilmayaptimi, tekshiring. Commit hali qilmang: keyingi darsda.

10. Real ishda

  • Kod tekshiruvida (code review) eng ko'p yoziladigan izohlardan biri: "bu "use client" ni pastroqqa tushirsa bo'ladimi?" Katta loyihalarda tepadagi bitta direktiva o'nlab kilobayt qo'shadi.
  • Bundle analiz — next build dan keyin qaysi kutubxona client to'plamiga tushganini ko'rish (Performance darsida next analyze).
  • server-only — sir yoki baza bilan ishlaydigan har modulning birinchi qatori: jamoa standarti sifatida ko'p loyihalarda majburiy.
  • Intervyu savoli: "Client Component serverda chiziladimi?" — ha, birinchi ochilishda; brauzerda esa jonlanadi. Bu savol ko'p nomzodni qoqiltiradi.

Xulosa

  • "use client" — client chegarasi (modul darajasida): shu fayl va uning hamma importlari brauzer to'plamiga qo'shiladi.
  • Bitta noto'g'ri import qimmat: marked client'da — 13.3 KB gzip; serverda — 0.
  • Client komponent ham serverda HTML'ga chiziladi; chizishda window yo'q — brauzer API hodisa yoki effektda.
  • "use client" ni barglarga qo'ying: kanonda 4 ta orol — jami ~3 KB.
  • server-only — server modulini client'ga tushishdan himoya; xatolar ro'yxatida chalg'ituvchi "Pages Router" matni bo'lishi mumkin.

Keyingi dars: Server va Client kompozitsiyasi — server komponentni client ichiga qanday "kiritish" va client chegarasidan nimalar o'ta oladi.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Next.js Client Components: "use client" direktivasi va client chegarasi — IlmHamroh