Thuta Learning
ရှာဖွေရန်
ProjectsWeb Developmentintermediate

Mini Project — Link Stash (Part 2): Add/Delete Feature နှင့် Filtering

စိတ်လျှော့ပါ။ ဒီခန်းကို စာအုပ်လိုမဟုတ်ဘဲ စကားပြောသလိုပဲ၊ နားလည်လွယ်အောင် ရှင်းပါမယ်။

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Mini Project — Link Stash (Part 2): Add/Delete Feature နှင့် Filtering ကို လက်တွေ့ project ထဲမှာ အသုံးချတတ်မယ်
  • ကိုယ်တိုင် code ရေးပြီး run ကြည့်တတ်မယ်
  • Project တစ်ခုလုံးကို အဆင့်လိုက် ဆောက်တတ်မယ်

ခဏလေး ဒီလိုပဲ စဉ်းစားကြည့်

Part 1 က static list ကို ဒီအဆင့်မှာ data-driven app အဖြစ်ပြောင်းပါမယ်။ Bookmark data တွေကို module-level array ကို simulate လုပ်တဲ့ lib/db.ts data layer တစ်ခုနဲ့ စီမံပြီး၊ Server Action နဲ့ form submit လုပ်တဲ့အခါ server မှာတိုက်ရိုက် insert/delete လုပ်ပါမယ်။ Client-side JavaScript disable ဖြစ်နေရင်တောင် form က အလုပ်လုပ်ဆဲဖြစ်အောင် progressive enhancement ကို လေ့လာရမှာပါ။ ဒါအပြင် home page ကို ?tag=docs လို search params နဲ့ filter လုပ်နိုင်အောင် ထည့်ပြီး၊ data ပြောင်းတိုင်း UI က အလိုအလျောက် update ဖြစ်အောင် revalidatePath ကိုသုံးပါမယ်။

လက်တွေ့ ဆောက်ကြည့်မယ်

lib/db.ts ဖန်တီးပြီး bookmarks array ကို module scope မှာထားကာ getBookmarks(), addBookmark(), deleteBookmark() function တွေ export လုပ်ပါ (real project မှာ SQLite/Prisma ကိုသုံးနိုင်ပေမယ့် ဒီ project အတွက် in-memory array နဲ့ ရိုးရှင်းစွာလုပ်ပါမယ်)။ app/actions.ts ထဲမှာ "use server" directive နဲ့ createBookmark, removeBookmark Server Actions ရေးပြီး revalidatePath("/") ခေါ်ပါ။ app/bookmarks/new/page.tsx မှာ form တစ်ခုဖန်တီးပြီး action={createBookmark} ချိတ်ပါ။ app/page.tsx ကို searchParams prop လက်ခံအောင်ပြင်ပြီး tag filter query နဲ့ list ကို filter လုပ်ပါ။ Bookmark card တစ်ခုချင်းစီမှာ delete button နဲ့ removeBookmark action ကိုချိတ်ပါ။

Code နမူနာ

typescript
// lib/db.ts
type Bookmark = { id: string; title: string; url: string; tags: string[] };

let bookmarks: Bookmark[] = [
  { id: "1", title: "Next.js Docs", url: "https://nextjs.org", tags: ["docs"] },
];

export function getBookmarks(tag?: string) {
  if (!tag) return bookmarks;
  return bookmarks.filter((b) => b.tags.includes(tag));
}

export function addBookmark(data: Omit<Bookmark, "id">) {
  bookmarks.push({ id: crypto.randomUUID(), ...data });
}

export function deleteBookmark(id: string) {
  bookmarks = bookmarks.filter((b) => b.id !== id);
}

// app/actions.ts
"use server";
import { revalidatePath } from "next/cache";
import { addBookmark, deleteBookmark } from "@/lib/db";

export async function createBookmark(formData: FormData) {
  const title = String(formData.get("title") ?? "").trim();
  const url = String(formData.get("url") ?? "").trim();
  if (!title || !url) return;
  addBookmark({ title, url, tags: [] });
  revalidatePath("/");
}

export async function removeBookmark(id: string) {
  deleteBookmark(id);
  revalidatePath("/");
}
You should see
Form ကနေ bookmark အသစ်ထည့်လိုက်ရင် home page ထဲမှာ card အသစ်ပေါ်လာပြီး၊ tag query param အလိုက် list ကလည်း filter ဖြစ်နေပါလိမ့်မယ်။

၅ မိနစ် စမ်းကြည့်

URL bar ထဲမှာ /?tag=docs နဲ့ /?tag=reference ကို ပြောင်းစမ်းကြည့်ပြီး filter result ကွဲပြားမှုကို 5 မိနစ်အတွင်း confirm လုပ်ပါ။

သတိလေးတစ်ချက်

in-memory array က server restart လုပ်တိုင်း data ပျောက်ပါတယ် — production project အတွက်ဆိုရင် database-layer သင်ခန်းစာမှာ ပြခဲ့တဲ့ Prisma/SQLite စတဲ့ real database ကို လက်တွေ့သုံးသင့်ပါတယ်။

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • Server Action ဖိုင်ထိပ်မှာ "use server" directive ထည့်ဖို့ မေ့တတ်ပြီး client component ကနေ import လုပ်တဲ့အခါ error တက်တတ်ပါတယ်
  • data ပြောင်းပြီးနောက် revalidatePath() ခေါ်ဖို့ မေ့သွားလို့ page ကို manual refresh မလုပ်ရင် UI အဟောင်းကိုပဲ မြင်ရနေတတ်ပါတယ်

အခု ကိုယ်တိုင် စမ်းကြည့်

URL bar ထဲမှာ /?tag=docs နဲ့ /?tag=reference ကို ပြောင်းစမ်းကြည့်ပြီး filter result ကွဲပြားမှုကို 5 မိနစ်အတွင်း confirm လုပ်ပါ။

You'll know it worked when: Form ကနေ bookmark အသစ်ထည့်လိုက်ရင် home page ထဲမှာ card အသစ်ပေါ်လာပြီး၊ tag query param အလိုက် list ကလည်း filter ဖြစ်နေပါလိမ့်မယ်။

Mini Project — Link Stash (Part 2): Add/Delete Feature နှင့် Filtering | Thuta Learning