Rumah > hujung hadapan web > tutorial js > Next.js Deep Dive: Membina Apl Nota dengan Ciri Lanjutan

Next.js Deep Dive: Membina Apl Nota dengan Ciri Lanjutan

DDD
Lepaskan: 2024-11-03 15:07:03
asal
1076 orang telah melayarinya

Next.js Deep Dive: Building a Notes App with Advanced Features## Pengenalan dan Objektif

Dalam artikel blog ini, saya ingin melihat ciri Next.js yang paling penting yang anda perlukan dalam senario praktikal.

Saya mencipta artikel blog ini sebagai rujukan tunggal untuk diri saya dan pembaca yang berminat. Daripada perlu melalui keseluruhan dokumentasi nextjs. Saya rasa lebih mudah untuk mempunyai artikel blog yang ringkas dengan semua ciri praktikal seterusnyajs penting yang boleh anda lawati secara berkala untuk menyegarkan pengetahuan anda!

Kami akan meneliti ciri di bawah bersama-sama sambil membina aplikasi nota secara selari.

  • Penghala Apl

    • Komponen Pelayan
    • Komponen Pelanggan
    • Penghalaan Bersarang
    • Laluan Dinamik
  • Pemuatan dan Pengendalian Ralat

  • Tindakan Pelayan

    • Membuat dan menggunakan tindakan pelayan
    • Menyepadukan tindakan pelayan dengan komponen klien
  • Pengambilan Data dan Cache

    • Menggunakan unstable_cache untuk cache sebelah pelayan 1. Mengesahkan semula cache dengan revalidateTag
    • Menggunakan unstable_cache untuk cache sebelah pelayan
  • Penstriman dan Saspens

    • Penstriman peringkat halaman dengan loading.tsx
    • Penstriman peringkat komponen menggunakan Suspense
  • Laluan Selari

    • Mencipta dan menggunakan slot bernama
    • Melaksanakan pemaparan serentak komponen berbilang halaman
  • Pengendalian Ralat

    • Melaksanakan sempadan ralat dengan error.tsx

Nota akhir kami mengambil kod aplikasi akan kelihatan seperti ini:

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Jangan ragu untuk melompat terus ke kod akhir yang boleh anda temui dalam spithacode repositori Github ini.

Jadi tanpa berlengah lagi, mari mulakan!

Next.js Deep Dive: Building a Notes App with Advanced Features

Konsep Utama

Sebelum menyelami perkembangan aplikasi nota kami, saya ingin memperkenalkan beberapa konsep nextjs utama yang penting untuk diketahui sebelum bergerak ke hadapan.

Penghala Apl

Penghala Aplikasi ialah direktori baharu "/app" yang menyokong banyak perkara yang tidak mungkin dalam direktori "/page" warisan seperti :

  1. Komponen Pelayan.
  2. Reka letak dikongsi: fail layout.tsx.
  3. Penghalaan Bersarang: anda boleh menyarangkan folder satu dalam satu lagi. Url laluan halaman akan mengikuti sarang folder yang sama. Contohnya, url sepadan halaman bersarang ini /app/notes/[noteId]/edit/page.tsx selepas mengandaikan bahawa parameter dinamik [noteId] adalah sama dengan "1" ialah "/notes/1/edit.

  4. Fail
  5. /loading.tsx yang mengeksport komponen yang dipaparkan apabila halaman distrim ke penyemak imbas pengguna.

  6. Fail
  7. /error.tsx yang mengeksport komponen yang dipaparkan apabila halaman melemparkan beberapa ralat yang tidak ditangkap.

  8. Penghalaan Selari dan banyak ciri yang akan kami lalui semasa membina aplikasi nota kami.

Komponen Pelayan vs Komponen Pelanggan

Mari kita mendalami topik yang sangat penting yang semua orang harus kuasai sebelum menyentuh Nextjs /app Penghala.

Komponen Pelayan

komponen pelayan pada asasnya ialah komponen yang dipaparkan pada pelayan.

Mana-mana komponen yang tidak didahului dengan arahan "use client" secara lalai ialah komponen pelayan termasuk halaman dan reka letak.

Komponen pelayan boleh berinteraksi dengan mana-mana API nodejs, atau mana-mana komponen yang dimaksudkan untuk digunakan pada pelayan.

Adalah mungkin untuk mendahului komponen pelayan dengan kata kunci async tidak seperti komponen klien. Jadi, anda boleh memanggil mana-mana fungsi tak segerak dan menunggunya sebelum memaparkan komponen.

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Anda mungkin terfikir mengapa malah pra-memaparkan komponen pada pelayan?

Jawapannya boleh diringkaskan dalam beberapa perkataan SEO, prestasi dan pengalaman pengguna.

Apabila pengguna melawat halaman, penyemak imbas memuat turun aset tapak web termasuk html, css dan javascript.

Himpunan javascript (yang termasuk kod rangka kerja anda) mengambil lebih banyak masa daripada aset lain untuk dimuatkan kerana saiznya.

  • Jadi pengguna perlu menunggu untuk melihat sesuatu pada skrin.

  • Perkara yang sama berlaku untuk perangkak yang bertanggungjawab mengindeks tapak web anda.

  • Banyak metrik SEO lain seperti LCP, TTFB, Kadar Lantunan,... akan terjejas.

Komponen Pelanggan

komponen klien hanyalah komponen yang dihantar ke penyemak imbas pengguna.

Komponen pelanggan bukan sekadar komponen html dan css yang terdedah. Mereka memerlukan interaktiviti untuk berfungsi jadi tidak mungkin untuk memaparkannya pada pelayan.

interaktiviti dijamin oleh sama ada rangka kerja javascript seperti react ( useState, useEffect) atau pelayar sahaja atau DOM API.

Perisytiharan komponen klien hendaklah didahului dengan arahan "use client". Yang memberitahu Nextjs untuk mengabaikan bahagian interaktifnya (useState,useEffect...) dan menghantarnya terus ke penyemak imbas pengguna.

/client-component.tsx

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Pilihalih Kebolehkomposan Berbeza.

Saya tahu, perkara yang paling mengecewakan dalam Nextjs, ialah pepijat pelik yang boleh anda hadapi jika anda terlepas peraturan bersarang antara Komponen Pelayan dan Komponen Pelanggan.

Jadi dalam bahagian seterusnya, kami akan menjelaskannya dengan mempamerkan pilih atur bersarang yang berbeza mungkin antara Komponen Pelayan dan Komponen Pelanggan.

Kami akan Melangkau dua pilih kasih ini kerana ia jelas dibenarkan: Komponen Pelanggan Komponen Pelanggan lain dan Komponen Pelayan di dalam Komponen Pelayan lain.

Memaparkan Komponen Pelayan sebagai Anak kepada Komponen Pelanggan

Anda boleh mengimport Komponen Pelanggan dan menjadikannya seperti biasa di dalam komponen pelayan. Pilih atur ini agak jelas kerana halaman dan reka letak adalah secara lalai komponen pelayan.

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Memaparkan Komponen Pelayan sebagai Anak kepada Komponen Pelanggan

Bayangkan menghantar komponen klien ke penyemak imbas pengguna dan kemudian menunggu komponen pelayan yang terletak di dalamnya untuk memaparkan dan mengambil data. Itu tidak mungkin kerana komponen pelayan sudah dihantar kepada pelanggan, Bagaimanakah anda boleh memaparkannya pada pelayan?

Itulah sebab pilih atur jenis ini tidak disokong oleh Nextjs.

Jadi sentiasa ingat untuk mengelak mengimport Komponen Pelayan di dalam Komponen Pelanggan untuk menjadikannya sebagai kanak-kanak.

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Sentiasa cuba kurangkan javascript yang dihantar ke penyemak imbas pengguna dengan menolak komponen klien ke bawah dalam pokok jsx.

Penyelesaian Penyelesaian Komponen Pelayan Di Dalam Komponen Pelanggan

Tidak mungkin untuk mengimport dan membuat Komponen Pelayan secara langsung sebagai anak kepada Komponen Pelanggan tetapi terdapat penyelesaian yang menggunakan sifat kebolehkomposisian bertindak balas.

Caranya ialah dengan melepasi Komponen Pelayan sebagai anak kepada Komponen Pelanggan pada komponen pelayan peringkat lebih tinggi ( Komponen ParentServer).

Mari kita panggil ia Tipu Papa :D.

Helah ini memastikan Komponen Pelayan yang diluluskan sedang dipaparkan di pelayan sebelum menghantar Komponen Pelanggan ke penyemak imbas pengguna.

import { ClientComponent } from '@/components'

// Allowed :)
export const ServerComponent = ()=>{

  return (
  <>

  <ClientComponent/>
  </>

  )
}



Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kami akan melihat contoh konkrit di /app/page.tsx halaman utama aplikasi nota kami.

Tempat kami akan memaparkan komponen pelayan yang diluluskan sebagai kanak-kanak dalam komponen klien. Komponen klien boleh menunjukkan atau menyembunyikan kandungan yang diberikan komponen pelayan bergantung pada nilai pembolehubah keadaan boolean.

Tindakan Pelayan

Tindakan pelayan ialah ciri nextjs yang menarik yang membenarkan panggilan dari jauh dan selamat fungsi yang diisytiharkan pada pelayan daripada komponen sisi klien anda .

Untuk mengisytiharkan tindakan pelayan anda hanya perlu menambah arahan "guna pelayan" ke dalam badan fungsi seperti yang ditunjukkan di bawah.

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Arahan "guna pelayan" memberitahu Nextjs bahawa fungsi itu mengandungi kod sisi pelayan yang hanya dilaksanakan pada pelayan.

Di bawah tudung Nextjs menghantar Id Tindakan dan mencipta titik tamat terpelihara untuk tindakan ini.

Jadi apabila anda memanggil tindakan ini dalam komponen klien Nextjs akan melaksanakan permintaan POST kepada titik akhir unik tindakan yang dikenal pasti oleh Id Tindakan sambil menghantar hujah bersiri yang telah anda hantar semasa memanggil tindakan dalam badan permintaan.

Mari kita jelaskan dengan lebih baik dengan contoh mudah ini.

Kami melihat sebelum ini, bahawa anda perlu menggunakan "guna pelayan" dalam arahan badan fungsi untuk mengisytiharkan tindakan pelayan. Tetapi bagaimana jika anda perlu mengisytiharkan sekumpulan tindakan pelayan sekaligus.

Nah, anda hanya boleh menggunakan arahan pada pengepala atau permulaan fail seperti yang ditunjukkan dalam kod di bawah.

/server/actions.ts

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Perhatikan bahawa tindakan pelayan hendaklah sentiasa ditandakan sebagai tidak segerak

  • Jadi dalam kod di atas, kami mengisytiharkan tindakan pelayan bernama createLogAction.

  • Tindakan ini bertanggungjawab untuk menyimpan entri log dalam fail tertentu pada pelayan di bawah direktori /logs.

  • Fail dinamakan berdasarkan argumen tindakan nama.

  • Tindakan Menambahkan entri log yang terdiri daripada tarikh penciptaan dan mesej hujah tindakan.

Sekarang, mari kita gunakan tindakan yang kami buat dalam CreateLogButton komponen bahagian pelanggan.

/komponen/CreateLogButton.tsx

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Komponen butang mengisytiharkan pembolehubah keadaan setempat bernama isSubmitting yang digunakan untuk menjejaki sama ada tindakan itu dilaksanakan atau tidak. Apabila tindakan sedang melaksanakan teks butang berubah daripada "Butang Log" kepada "Memuatkan...".

tindakan pelayan dipanggil apabila kita mengklik pada komponen Butang Log.

Persediaan Logik Perniagaan

Mencipta model Nota kami

Pertama sekali, mari mulakan dengan mencipta skema dan jenis pengesahan Nota kami.

Memandangkan model sepatutnya mengendalikan pengesahan data, kami akan menggunakan perpustakaan popular untuk tujuan itu yang dipanggil zod.

Perkara menarik tentang zod ialah API deskriptifnya yang mudah difahami yang menjadikan penentuan model dan penjanaan TypeScript yang sepadan sebagai tugas yang lancar.

Kami tidak akan menggunakan model kompleks yang mewah untuk nota kami. Setiap nota akan mempunyai id unik, tajuk, kandungan dan medan tarikh penciptaan.

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kami juga mengisytiharkan beberapa skema tambahan yang berguna seperti InsertNoteSchema dan WhereNoteSchema yang akan menjadikan hidup kami lebih mudah apabila kami mencipta fungsi boleh guna semula kami yang memanipulasi model kami kemudian.

Mencipta pangkalan data dalam memori yang mudah

Kami akan menyimpan dan memanipulasi nota kami dalam ingatan.

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kami menyimpan tatasusunan nota kami dalam objek global ini untuk mengelakkan kehilangan keadaan tatasusunan kami setiap kali pemalar nota diimport ke dalam fail (muat semula halaman...).

Mencipta kes penggunaan aplikasi kami

Cipta Kes Penggunaan Nota

Kes penggunaan createNote akan membolehkan kami memasukkan nota ke dalam tatasusunan nota. Fikirkan kaedah notes.unshift sebagai songsangan kaedah notes.push kerana ia menolak elemen ke permulaan tatasusunan dan bukannya penghujungnya.

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kemas kini Kes Penggunaan Nota

Kami akan menggunakan Nota kemas kini untuk mengemas kini nota tertentu dalam tatasusunan nota yang diberikan idnya. Ia mula-mula mencari indeks unsur, membuang ralat jika ia tidak ditemui dan mengembalikan nota yang sepadan berdasarkan indeks yang ditemui.

import { ClientComponent } from '@/components'

// Allowed :)
export const ServerComponent = ()=>{

  return (
  <>

  <ClientComponent/>
  </>

  )
}



Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Padamkan Kes Penggunaan Nota

Fungsi kes guna deleteNote akan digunakan untuk memadam nota yang diberikan diberikan id nota.
Kaedah ini berfungsi sama, mula-mula ia mencari indeks nota yang diberikan idnya, membuang ralat jika ia tidak ditemui kemudian mengembalikan nota sepadan yang diindeks oleh id yang ditemui.

"use client"
import { ServerComponent } from '@/components'

// Not allowed :(
export const ClientComponent = ()=>{

  return (
  <>

  <ServerComponent/>
  </>

  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dapatkan Note Use Case

Fungsi getNote adalah jelas, ia hanya akan mencari nota yang diberikan idnya.

import {ClientComponent} from '@/components/...'
import {ServerComponent} from '@/components/...'

export const ParentServerComponent = ()=>{

  return (
  <>
  <ClientComponent>
     <ServerComponent/>
  </ClientComponent>

</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dapatkan Kes Penggunaan Nota

Memandangkan kami tidak mahu menolak keseluruhan pangkalan data nota kami ke sisi pelanggan, kami hanya akan mengambil sebahagian daripada jumlah nota yang tersedia. Oleh itu, kita perlu melaksanakan penomboran sebelah pelayan.

export const Component = ()=>{

  const serverActionFunction = async(params:any)=>{
    "use server"
    // server code lives here
    //...
    /

  }
  const handleClick = ()=>{
  await serverActionFunction()


  }

  return <button onClick={handleClick}>click me</button>
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Jadi fungsi getNotes pada asasnya akan membolehkan kami mengambil halaman tertentu daripada pelayan kami dengan menghantar hujah halaman.
Argumen had berfungsi untuk menentukan bilangan item yang terdapat pada halaman tertentu.

Contohnya:
Jika tatasusunan nota mengandungi 100 elemen dan hujah had bersamaan dengan 10.

Dengan meminta halaman 1 dari pelayan kami hanya 10 item pertama akan dikembalikan.

Argumen carian akan digunakan untuk melaksanakan carian sebelah pelayan. Ia akan memberitahu pelayan untuk hanya mengembalikan nota yang mempunyai carian Rentetan sebagai subrentetan sama ada dalam tajuk atau atribut kandungan.

Dapatkan Kes Penggunaan Ringkasan Nota

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dapatkan Kes Penggunaan Aktiviti Terkini

Kes penggunaan ini akan digunakan untuk mendapatkan beberapa data palsu tentang aktiviti terbaru pengguna.

Kami akan menggunakan fungsi ini dalam halaman /papan pemuka.

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dapatkan Kes Penggunaan Teg Terkini

Fungsi use case ini akan bertanggungjawab untuk mendapatkan statistik tentang teg berbeza yang digunakan dalam nota kami (#something).

Kami akan menggunakan fungsi ini dalam halaman /papan pemuka.

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dapatkan Kes Penggunaan Maklumat Pengguna

Kami akan menggunakan fungsi use case ini untuk hanya mengembalikan beberapa data palsu tentang beberapa maklumat pengguna seperti nama, e-mel...

Kami akan menggunakan fungsi ini dalam halaman /papan pemuka.

import { ClientComponent } from '@/components'

// Allowed :)
export const ServerComponent = ()=>{

  return (
  <>

  <ClientComponent/>
  </>

  )
}



Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dapatkan Kes Penggunaan Nota Rawak

"use client"
import { ServerComponent } from '@/components'

// Not allowed :(
export const ClientComponent = ()=>{

  return (
  <>

  <ServerComponent/>
  </>

  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Tindakan dan Caching Pelayan Penghala Apl

Halaman Utama ( Demo Penyelesaian Komponen Pelayan Dalam Komponen Pelanggan)

Dalam halaman utama ini, kami akan menunjukkan helah atau penyelesaian sebelumnya untuk memaparkan Komponen Pelayan di dalam Komponen Pelanggan (Helah PaPa :D) .

/app/page.tsx

import {ClientComponent} from '@/components/...'
import {ServerComponent} from '@/components/...'

export const ParentServerComponent = ()=>{

  return (
  <>
  <ClientComponent>
     <ServerComponent/>
  </ClientComponent>

</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dalam kod di atas kami mengisytiharkan Komponen Pelayan Induk dipanggil Home yang bertanggungjawab untuk memaparkan halaman "/" dalam aplikasi kami.

Kami mengimport Komponen Pelayan bernama RandomNote dan Komponen Pelanggan bernama NoteOfTheDay.

Kami menghantar RandomNote Komponen Pelayan sebagai kanak-kanak kepada NoteOfTheDay Komponen Bahagian Pelanggan.

/app/components/RandomNote.ts

export const Component = ()=>{

  const serverActionFunction = async(params:any)=>{
    "use server"
    // server code lives here
    //...
    /

  }
  const handleClick = ()=>{
  await serverActionFunction()


  }

  return <button onClick={handleClick}>click me</button>
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Komponen Pelayan RandomNote berfungsi seperti berikut:

  • ia mengambil nota rawak menggunakan fungsi kes penggunaan getRandomNote.

  • ia memaparkan butiran nota yang terdiri daripada tajuk dan bahagian atau subrentetan nota penuh kandungan.

/app/components/NoteOfTheDay.ts

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Komponen Pelanggan NoteOfTheDay di sisi lain berfungsi seperti yang diterangkan di bawah:

  • Ia mengambil prop kanak-kanak sebagai input (yang akan menjadi komponen pelayan RandomNote kami dalam kes kami), dan kemudian menjadikannya secara bersyarat bergantung pada isVisible nilai pembolehubah keadaan boolean.
  • Komponen ini juga memaparkan butang dengan pendengar acara onClick dilampirkan padanya, untuk menogol nilai keadaan keterlihatan.

Halaman Nota

/app/notes/page.tsx

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kami akan bermula dengan mencipta halaman /app/notes/page.tsx yang merupakan komponen pelayan yang bertanggungjawab untuk:

  1. Mendapatkan parameter carian halaman yang merupakan rentetan yang dilampirkan di hujung URL selepas tanda ?: http://localhost:3000/notes?page=1&search=Sesuatu

  2. Melalukan parameter carian ke dalam fungsi yang diisytiharkan secara setempat yang dipanggil fetchNotes.

  3. Fungsi fetchNotes menggunakan fungsi use case kami yang diisytiharkan sebelum ini getNotes untuk mengambil halaman nota semasa.

  4. Anda dapat melihat bahawa kami sedang membungkus fungsi getNotes dengan fungsi utiliti yang diimport daripada "next/cache" dipanggil unstable_cache. Fungsi cache tidak stabil digunakan untuk cache respons daripada fungsi getNotes.

Jika kami pasti tiada nota ditambahkan pada pangkalan data. Tidak masuk akal untuk memukulnya setiap kali halaman dimuat semula. Jadi fungsi unstable_cache ialah menandai hasil fungsi getNotes dengan tag "nota" yang boleh kita gunakan kemudian untuk membatalkan "nota" cache jika nota ditambah atau dipadamkan.

  1. Fungsi fetchNotes mengembalikan dua nilai: nota dan jumlah.

  2. Data yang terhasil (nota dan jumlah) dihantar ke Komponen Sebelah Pelanggan dipanggil NotesList yang bertanggungjawab untuk memaparkan nota kami.

Apabila pengguna menekan muat semula. Halaman kosong akan muncul kepada pengguna semasa data nota kami sedang diambil.
Untuk menyelesaikan masalah itu, kami akan menggunakan ciri Nextjs hebat yang dipanggil. Penstriman Halaman Sisi Pelayan.

Kita boleh melakukannya dengan mencipta fail loading.tsx, di sebelah fail /app/notes/page.tsx kami.

/app/notes/loading.tsx

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Semasa halaman itu distrim daripada pelayan, pengguna akan melihat halaman memuatkan rangka, yang memberi pengguna idea tentang jenis kandungan yang akan datang.

Next.js Deep Dive: Building a Notes App with Advanced Features

Bukankah itu keren :). cuma buat fail loading.tsx dan voila anda sudah selesai. ux anda berkembang maju ke peringkat seterusnya.

/app/notes/components/NotesList.tsx

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Senarai Nota Komponen Sebelah Pelanggan Menerima nota dan data berkaitan penomboran daripada induknya Komponen Pelayan iaitu Halaman Nota.

Kemudian komponen mengendalikan pemaparan halaman semasa nota. Setiap kad nota individu diberikan menggunakan komponen NoteView.

Ia juga menyediakan pautan ke halaman sebelumnya dan seterusnya menggunakan komponen Next.js Pautan yang penting untuk pra-mengambil data halaman seterusnya dan sebelumnya untuk membolehkan kami mempunyai pelanggan yang lancar dan pantas -navigasi sisi.

Untuk mengendalikan Carian Sisi Pelayan kami menggunakan cangkuk tersuai dipanggil useNotesSearch yang pada asasnya mengendalikan mencetuskan pengambilan semula nota apabila pengguna menaip pertanyaan tertentu dalam carian Input.

/app/notes/components/NoteView.ts

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Komponen NoteView adalah mudah, ia hanya bertanggungjawab untuk memberikan setiap kad nota individu dengan yang sepadan: tajuk, sebahagian daripada kandungan dan pautan tindakan untuk melihat butiran nota atau untuk mengeditnya.

/app/notes/components/hooks/use-notes-search.ts

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kait tersuai useNotesSearch berfungsi seperti berikut:

  1. Ia menyimpan prop initialSearch dalam keadaan setempat menggunakan cangkuk useState.

  2. Kami menggunakan cangkuk useEffect React untuk mencetuskan navigasi halaman apabila nilai pembolehubah currentPage atau debouncedSearchValue.

  3. URL halaman baharu dibina sambil mengambil kira halaman semasa dan nilai carian.

  4. Fungsi setSearch akan dipanggil setiap kali aksara berubah apabila pengguna menaip sesuatu dalam Input carian. Itu akan menyebabkan terlalu banyak navigasi dalam masa yang singkat.

  5. Untuk mengelakkannya kami hanya mencetuskan navigasi apabila pengguna berhenti menaip dalam istilah lain, kami menyahlantunkan nilai carian untuk tempoh masa tertentu (300ms dalam kes kami).

Cipta Nota

Seterusnya, mari kita lihat /app/notes/create/page.tsx yang merupakan pembalut komponen pelayan di sekitar komponen klien CreateNoteForm.

Next.js Deep Dive: Building a Notes App with Advanced Features

/app/notes/create/page.tsx

import { ClientComponent } from '@/components'

// Allowed :)
export const ServerComponent = ()=>{

  return (
  <>

  <ClientComponent/>
  </>

  )
}



Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

/app/notes/create/components/CreateNoteForm.tsx

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Borang komponen klien CreateNoteForm bertanggungjawab untuk mendapatkan semula data daripada pengguna kemudian menyimpannya dalam pembolehubah keadaan setempat (tajuk, kandungan).

Apabila borang diserahkan selepas mengklik pada butang hantar createNoteAction akan diserahkan dengan tajuk dan kandungan hujah negeri setempat .

Pembolehubah boolean keadaan isSubmitting digunakan untuk menjejak status penyerahan tindakan.

Jika createNoteAction berjaya diserahkan tanpa sebarang ralat, kami mengubah hala pengguna ke halaman /notes.

/app/notes/create/actions/create-note.action.tsx

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kod tindakan createNoteAction adalah mudah, fail yang mengandungi didahului dengan arahan "use server" yang menunjukkan kepada Next.js bahawa tindakan ini boleh dipanggil dalam komponen klien.

Satu perkara yang harus kami tekankan tentang tindakan pelayan ialah hanya antara muka tindakan dihantar kepada klien tetapi bukan kod di dalam tindakan itu sendiri.

Dalam istilah lain, kod di dalam tindakan akan hidup pada pelayan, jadi kami tidak seharusnya mempercayai sebarang input yang datang daripada klien ke pelayan kami.

Itulah sebabnya kami menggunakan zod di sini untuk mengesahkan rawNote hujah tindakan menggunakan skema kami yang telah dibuat sebelum ini.

Selepas mengesahkan input kami, kami memanggil kes penggunaan createNote dengan data yang disahkan.

Jika nota berjaya dibuat, fungsi revalidateTag akan dipanggil untuk membatalkan entri cache yang ditag sebagai "nota" (Ingat fungsi unstable_cache yang digunakan dalam halaman /nota).

Halaman Butiran Nota

Halaman butiran nota memaparkan tajuk dan kandungan penuh nota tertentu berdasarkan id uniknya. Selain itu, ia menunjukkan beberapa butang tindakan untuk mengedit atau memadam nota.

Next.js Deep Dive: Building a Notes App with Advanced Features

/app/notes/[noteId]/page.tsx

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
  1. Mula-mula kami mendapatkan semula param halaman daripada prop halaman. Dalam Next.js 13 kita perlu menunggu hujah halaman params kerana ia adalah janji.

  2. Selepas melakukan itu, kami menghantar params.noteId ke fetchNote fungsi yang diisytiharkan secara tempatan.

/app/notes/[noteId]/fetchers/fetch-note.ts

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
  1. Fungsi fetchNote membungkus kes penggunaan getNote kami dengan unstable_cache sambil menandakan hasil yang dikembalikan dengan "nota-detail" dan butiran nota/${id} Teg.

  2. Teg "nota-butiran" boleh digunakan untuk membatalkan semua entri cache butiran nota sekaligus.

  3. Sebaliknya, teg note-details/${id} hanya dikaitkan dengan nota tertentu yang ditakrifkan oleh id uniknya. Jadi kita boleh menggunakannya untuk membatalkan kemasukan cache nota tertentu dan bukannya keseluruhan set nota.

/app/notes/[noteId]/loading.tsx

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Peringatan

loading.tsx ialah halaman Next.js khas yang dipaparkan semasa halaman butiran nota sedang mengambil datanya di pelayan.

Atau dalam istilah lain semasa fungsi fetchNote sedang melaksanakan halaman rangka akan ditunjukkan kepada pengguna dan bukannya skrin kosong.

Ciri nextjs ini dipanggil Penstriman Halaman. Ia membolehkan anda menghantar keseluruhan reka letak induk statik halaman dinamik semasa menstrim kandungannya secara beransur-ansur.

Ini meningkatkan prestasi dan pengalaman pengguna dengan mengelak daripada menyekat ui semasa kandungan dinamik halaman sedang diambil pada pelayan.

/app/notes/[noteId]/components/DeleteNoteButton.tsx

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Sekarang mari kita selami DeleteNoteButton komponen bahagian klien.

Next.js Deep Dive: Building a Notes App with Advanced Features

Komponen bertanggungjawab untuk memaparkan butang padam dan melaksanakan deleteNoteAction kemudian mengubah hala pengguna ke halaman /notes apabila tindakan itu berjaya dilaksanakan.

Untuk menjejak status pelaksanaan tindakan kami menggunakan pembolehubah keadaan setempat isDeleting.

/app/notes/[noteId]/actions/delete-note.action.tsx

import { ClientComponent } from '@/components'

// Allowed :)
export const ServerComponent = ()=>{

  return (
  <>

  <ClientComponent/>
  </>

  )
}



Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kod deleteNoteAction berfungsi seperti berikut:

  1. Ia menggunakan zod untuk menghuraikan dan mengesahkan input tindakan.
  2. Setelah memastikan input kami selamat, kami menghantarnya ke deleteNote fungsi use case kami.
  3. Apabila tindakan berjaya dilaksanakan, kami menggunakan revalidateTag untuk membatalkan kedua-dua "notes" dan note-details/${where.id} cache penyertaan.

Edit Halaman Nota

Next.js Deep Dive: Building a Notes App with Advanced Features

/app/notes/[noteId]/edit/page.tsx

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Halaman /app/notes/[noteId]/edit/page.tsx ialah komponen pelayan yang mendapat param noteId daripada janji params.

Kemudian ia mengambil nota menggunakan fungsi fetchNote.

Selepas pengambilan berjaya. Ia menyerahkan nota kepada EditNoteForm komponen bahagian klien.

/app/notes/[noteId]/edit/components/EditNoteForm.tsx

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Komponen bahagian sisi klien EditNoteForm menerima nota dan memberikan borang yang membolehkan pengguna mengemas kini butiran nota.

Pembolehubah keadaan setempat tajuk dan kandungan digunakan untuk menyimpan nilai input atau kawasan teks yang sepadan.

Apabila borang diserahkan melalui butang Kemas Kini Nota. updateNoteAction dipanggil dengan tajuk dan nilai kandungan sebagai argumen.

Pembolehubah keadaan isSubmitting digunakan untuk menjejak status penyerahan tindakan, membenarkan untuk menunjukkan penunjuk pemuatan apabila tindakan sedang dilaksanakan.

/app/notes/[noteId]/edit/actions/edit-note.action.ts

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Tindakan updateNoteAction berfungsi seperti berikut:

  1. Input tindakan disahkan menggunakan skema zod yang sepadan (WhereNoteSchema dan InsertNoteSchema).
  2. Selepas itu updateNote fungsi use case dipanggil dengan data yang dihuraikan dan disahkan.
  3. Selepas mengemas kini nota berjaya, kami mengesahkan semula teg "nota" dan nota-details/${where.id}.

Halaman Papan Pemuka (Ciri Penstriman Tahap Komponen)

/app/dashboard/page.tsx

import { ClientComponent } from '@/components'

// Allowed :)
export const ServerComponent = ()=>{

  return (
  <>

  <ClientComponent/>
  </>

  )
}



Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Halaman /app/dashboard/page.tsx dipecahkan kepada komponen sisi pelayan yang lebih kecil: Ringkasan Nota, RecentActivity dan TagCloud.

Setiap komponen pelayan mengambil datanya sendiri secara berasingan.

Setiap komponen pelayan dibalut dengan React Suspense Sempadan.

Peranan sempadan suspens adalah untuk memaparkan komponen sandaran(a Skeleton dalam kes kami) Apabila komponen pelayan kanak-kanak sedang mengambil datanya sendiri.

Atau dalam istilah lain sempadan Suspense membenarkan kami menangguhkan atau menangguhkan pemberian anak-anaknya sehingga beberapa syarat dipenuhi( Data di dalam kanak-kanak sedang dimuatkan).

Jadi pengguna akan dapat melihat halaman sebagai gabungan sekumpulan rangka. Semasa respons untuk setiap komponen individu sedang distrim oleh pelayan.

Satu kelebihan utama pendekatan ini adalah untuk mengelak daripada menyekat ui jika satu atau lebih komponen pelayan mengambil lebih banyak masa berbanding yang lain.

Jadi, jika kita mengandaikan bahawa masa pengambilan individu untuk setiap komponen diedarkan seperti berikut:

  1. Ringkasan Nota mengambil masa 2 saat untuk dimuatkan.
  2. Aktiviti Terkini mengambil masa 1 saat untuk dimuatkan.
  3. TagCloud mengambil masa 3 saat untuk dimuatkan.

Apabila kita menekan muat semula, perkara pertama yang akan kita lihat ialah 3 pemuat rangka.

Selepas 1 saat komponen RecentActivity akan muncul.
Selepas 2 saat NotesSummary akan mengikuti kemudian TagCloud.

Jadi daripada membuat pengguna menunggu selama 3 saat sebelum melihat sebarang kandungan. Kami mengurangkan masa itu sebanyak 2 saat dengan menunjukkan Aktiviti Terkini dahulu.

Pendekatan pemaparan tambahan ini menghasilkan pengalaman dan prestasi pengguna yang lebih baik.

Next.js Deep Dive: Building a Notes App with Advanced Features

Kod untuk Komponen Pelayan individu diserlahkan di bawah.

/app/dashboard/components/RecentActivity.tsx

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Komponen pelayan RecentActivity pada asasnya mengambil aktiviti terakhir menggunakan fungsi kes penggunaan getRecentActivity dan menjadikannya dalam senarai tidak tertib.

/app/papan pemuka/komponen/TagCloud.tsx

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Komponen sisi pelayan TagCloud diambil kemudian memaparkan semua nama tag yang digunakan dalam kandungan nota dengan kiraan masing-masing.

/app/dashboard/components/NotesSummary.tsx

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Komponen pelayan NotesSummary memaparkan maklumat ringkasan selepas mengambilnya menggunakan getNoteSummary fungsi use case.

Halaman Profil (Ciri Laluan Selari)

Sekarang mari kita beralih ke halaman profil di mana kita akan melalui ciri nextjs yang menarik dipanggil Laluan Selari.

Laluan selari membolehkan kami secara serentak atau bersyarat memaparkan satu atau lebih halaman dalam reka letak yang sama.

Dalam contoh kami di bawah, kami akan memaparkan halaman maklumat pengguna dan halaman nota pengguna dalam reka letak yang sama iaitu /app/profile .

Anda boleh mencipta Laluan Selari dengan menggunakan slot bernama. Slot bernama diisytiharkan betul-betul sebagai subhalaman tetapi simbol @ harus mendahului nama folder tidak seperti halaman biasa.

Sebagai contoh, dalam folder /app/profile/ kami akan mencipta dua slot bernama:

  1. /app/profile/@info untuk halaman maklumat pengguna.
  2. /app/profile/@notes untuk halaman nota pengguna.

Next.js Deep Dive: Building a Notes App with Advanced Features

Sekarang mari buat fail reka letak /app/profile/layout.tsx fail yang akan menentukan reka letak halaman /profile kami.

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Seperti yang anda lihat daripada kod di atas, kami kini mendapat akses kepada maklumat dan nota param yang mengandungi kandungan di dalam halaman @info dan @nota.

Jadi halaman @info akan dipaparkan di sebelah kiri dan @nota akan dipaparkan di sebelah kanan.

Kandungan dalam page.tsx (dirujuk oleh kanak-kanak) akan dipaparkan di bahagian bawah halaman.

@halaman maklumat

/app/profile/@info/page.tsx

export const ServerComponent = async ()=>{
  const posts = await getSomeData()
  // call any nodejs api or server function during the component rendering

  // Don't even think about it. No useEffects are allowed here x_x

  const pasta = await getPasta()

  return (
  <ul>
  {
      data.map(d=>(
      <li>{d.title}</li>

      ))

    }
  </ul>
  )

}

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

UserInfoPage ialah komponen pelayan yang akan mengambil maklumat pengguna menggunakan getUserInfo fungsi use case.

Rangka sandaran di atas akan dihantar ke penyemak imbas pengguna apabila komponen sedang mengambil data dan dipaparkan pada pelayan (Server Side Streaming).

/app/profile/@info/loading.tsx

"use client"
import React,{useEffect,useState} from "react"

export const ClientComponent = ()=>{
  const [value,setValue] = useState()

  useEffect(()=>{
    alert("Component have mounted!")

    return ()=>{
      alert("Component is unmounted")
    }
  },[])
  //..........
  return (
  <>
  <button onClick={()=>alert("Hello, from browser")}></button>
{/* .......... JSX Code ...............*/}
</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

@nota Halaman

Perkara yang sama berlaku untuk LastNotesPage komponen bahagian pelayan. ia akan mengambil data dan membuat pada pelayan sementara ui rangka sedang dipaparkan kepada pengguna

/app/profile/@notes/page.tsx

import { ClientComponent } from '@/components'

// Allowed :)
export const ServerComponent = ()=>{

  return (
  <>

  <ClientComponent/>
  </>

  )
}



Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

/app/profile/@notes/loading.tsx

"use client"
import { ServerComponent } from '@/components'

// Not allowed :(
export const ClientComponent = ()=>{

  return (
  <>

  <ServerComponent/>
  </>

  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Halaman Ralat

Sekarang mari kita terokai ciri yang cukup bagus dalam Nextjs halaman error.tsx.

Next.js Deep Dive: Building a Notes App with Advanced Features

Apabila anda menggunakan aplikasi anda ke pengeluaran, anda pasti mahu memaparkan ralat mesra pengguna apabila ralat tidak ditangkap dilemparkan daripada salah satu halaman anda.

Di situlah fail error.tsx masuk.

Mari kita buat halaman contoh dahulu yang melemparkan ralat tidak ditangkap selepas beberapa saat.

/app/error-page/page.tsx

import {ClientComponent} from '@/components/...'
import {ServerComponent} from '@/components/...'

export const ParentServerComponent = ()=>{

  return (
  <>
  <ClientComponent>
     <ServerComponent/>
  </ClientComponent>

</>
  )
}


Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Apabila halaman tidur atau menunggu untuk fungsi tidur dilaksanakan. Halaman pemuatan di bawah akan ditunjukkan kepada pengguna.

/app/error-page/loading.tsx

export const Component = ()=>{

  const serverActionFunction = async(params:any)=>{
    "use server"
    // server code lives here
    //...
    /

  }
  const handleClick = ()=>{
  await serverActionFunction()


  }

  return <button onClick={handleClick}>click me</button>
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Selepas beberapa saat ralat akan dibuang dan mencatat halaman anda :(.

Untuk mengelakkannya, kami akan mencipta fail error.tsx yang mengeksport komponen yang akan bertindak sebagai Sempadan Ralat untuk /app/error-page/page .tsx.

/app/error-page/error.tsx

- app/
  - notes/ --------------------------------> Server Side Caching Features
    - components/
      - NotesList.tsx
    - [noteId]/
      - actions/ -------------------------> Server Actions feature
        - delete-note.action.ts
        - edit-note.action.ts
      - components/
        - DeleteButton.tsx
      - page.tsx
      - edit/
        - components/
          - EditNoteForm.tsx
        - page.tsx
        - loading.tsx --------------------> Page level Streaming feature
    - create/
      - actions/
        - create-note.action.ts
      - components/
        - CreateNoteForm.tsx
      - page.tsx
  - error-page/
    - page.tsx
    - error.tsx --------------------------> Error Boundary as a page feature
  - dashboard/ ---------------------------> Component Level Streaming Feature
    - components/
      - NoteActivity.tsx
      - TagCloud.tsx
      - NotesSummary.tsx
    - page.tsx
  - profile/ ----------------------------->[6] Parallel Routes Feature
    - layout.tsx
    - page.tsx
    - @info/
      - page.tsx
      - loading.tsx
    - @notes/
      - page.tsx
      - loading.tsx
- core/ --------------------------> Our business logic lives here
  - entities/
    - note.ts
  - use-cases/
    - create-note.use-case.ts
    - update-note.use-case.ts
    - delete-note.use-case.ts
    - get-note.use-case.ts
    - get-notes.use-case.ts
    - get-notes-summary.use-case.ts
    - get-recent-activity.use-case.ts
    - get-recent-tags.use-case.ts

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kesimpulan

Dalam panduan ini, kami telah meneroka ciri utama Next.js dengan membina aplikasi nota praktikal. Kami telah membincangkan:

  1. Penghala Apl dengan Komponen Pelayan dan Pelanggan
  2. Pemuatan dan Pengendalian Ralat
  3. Tindakan Pelayan
  4. Pengambilan Data dan Cache
  5. Penstriman dan Saspens
  6. Laluan Selari
  7. Sempadan Ralat

Dengan menggunakan konsep ini dalam projek dunia sebenar, kami telah memperoleh pengalaman praktikal dengan keupayaan hebat Next.js. Ingat, cara terbaik untuk mengukuhkan pemahaman anda adalah melalui latihan.

Langkah Seterusnya

  • Terokai kod lengkap: github.com/spithacode/next-js-features-notes-app
  • Lanjutkan aplikasi dengan ciri anda sendiri
  • Kekal dikemas kini dengan dokumentasi rasmi Next.js

Jika anda mempunyai sebarang pertanyaan atau ingin membincangkan sesuatu dengan lebih lanjut, sila hubungi saya di sini.

Selamat pengekodan!

Atas ialah kandungan terperinci Next.js Deep Dive: Membina Apl Nota dengan Ciri Lanjutan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan