Sitemap
Duha Yıldırım

Duha Yıldırım

Software engineer -my experience with the code-

Next.js ile Todo uygulaması (dynamic route, route group, revalidation, metadata, pre-rendering, json-server, nested layout, api route)

6 min readMar 26, 2024

Merhaba!
Next.js ve Supabase kullanarak geliştirilecek bir uygulamanın temelini atmak istiyorum. Auth, oauth, recover, CRUD gibi işlemleri göstermek istemiştim ama öncesinde bu işlemleri üzerinde uygulayabileceğim basic bir proje oluşturmam gerekti. Ben de bu sebeple önce sadece next.js ile hızlı temel bir bir todo uygulaması geliştirmek istedim. Next.js kullanarak hızlı bir temel todo uygulaması geliştirmeyi düşündüm.
Basic bir to do uygulaması olarak gözükse de içinde dynamic route, route group, revalidation, metadata, pre-rendering(generateStaticParams), json-server, nested layout, api route gibi konulara da değinmeye çalıştım.

Get Duha Yıldırım’s stories in your inbox

Join Medium for free to get updates from this writer.

İşe aşağıdaki komutu çalıştırarak başladım. Bulunduğum dizine bir next projesi oluşturuyorum ve daha sonra aşağıdaki seçenekleri tercih ettim:

npx create-next-app@latest ./
Would you like to use TypeScript? Yes
Would you like to use ESLint? No
Would you like to use Tailwind CSS? No
Would you like to use `src/` directory? No
Would you like to use App Router? (recommended) Yes
Would you like to customize the default import alias (@/*)? No

Projemiz oluştuktan sonra, bazı hazırlıklar yapmam gerekiyordu:

  • app/page.tsx dosyasındaki kodları temizledim.
  • app/global.css dosyasındaki Tailwind CSS dışındaki kodları kaldırdım ve yerine example.css adresindeki CSS dosyalarını ekledim. Uygulama boyunca CSS yazımını minimum seviyede tutmayı planlıyorum.
  • tsconfig.json dosyasına “baseUrl”: “.” propetysini ekledim.
  • app klasörü içinde bileşenlerimi tutacak bir components klasör oluşturdum.
  • İlerleyen aşamalarda bir veritabanıyla çalışacağımızı düşünerek, şimdilik fake verilere ihtiyacımız olduğunu fark ettim. Bu nedenle, data adında bir klasör oluşturdum ve içine DummyData.json adında bir dosya ekleyip fake todo verileriyle doldurdum. Bu verilere fake data üzerinden erişebilirsiniz.
  • Sonrasında, bir terminal açıp
    npm install json-server -g komutu
    ile oluşturduğum JSON dosyasını sunacak paketi yükledim.
    Ardından terminalde
    json-server — watch — port 4000 ./data/DummyData.json
    komutunu çalıştırarak sunucuyu başlattım.

Artık uygulamamızı geliştirmeye başlayabiliriz. İlk adım olarak, proje için bir düzen oluşturmak önemli. Bunun için bir tasarım oluşturuyorum, böylece sayfa içi yönlendirmeleri kolaylaştıracağım.
Hemen basit bir navbar tasarlayarak başlıyorum. Bunun için components klasörüne navbar.tsx dosyasını ekledim.

Sonra, navbar.tsx bileşenimi layout.tsx içinde çağırdım.
Şimdi, app klasörü içinde yeni bir statik sayfa oluşturmak için todos adında bir klasör oluşturuyorum. İçine page.tsx ve TodoList.tsx adında iki dosya ekliyorum.
page.tsx: Todolarımı listeleyecek ve Next.js tarafından statik bir sayfa olarak işlenecek.
TodoList.tsx: veri ekleme, silme, güncelleme ve listeleme gibi işlemleri gerçekleştirecek ve daha sonra page.tsx tarafından çağrılacak.
Todo’ları listeleme işlevini aşağıdaki gibi tasarladım:

Bu kod parçası, HTTP isteği göndererek todo verilerini alır ve liste oluşturur. Eğer bir hata oluşursa, uygun bir şekilde işler.
Kodda dikkatinizi çekmek istediğim asıl kısım; sayfanın client tarafında çalışmasına rağmen next.js’in sunduğu *revalidate* özelliği sayesinde SSR çalışan bu sayfa belirlenen süre sonrasında yeniden oluşturulmasını sağlanıyor.
Uygulamanın anlık görüntüsü resimdeki gibidir.

Press enter or click to view image in full size

Artık todo’ları listeleme işlevini gerçekledik. Bir sonraki adımda, bir todo’nun detay sayfasını dynamic route ile oluşturalım.

Ardından, sayfanın kodlamasına başlayalım ve getTodo fonksiyonunu yazarak belirli bir Todo’nun detaylarını almak için bir API isteği yapalım ve aldığı bilgileri JSON formatında geri döndürelim.

TodoDetail bileşenini, belirli bir Todo’nun detaylarını ekranda göstermek için tasarladım. Bu bileşen, bir parametre olarak { params } alır; bu parametre, Todo’nun id değerini içermelidir. getTodo fonksiyonu kullanılarak belirtilen id’ye sahip Todo’nun detayları alınır ve ekranda gösterilir.
Ardından, todo list sayfamızda listelenen todolardan detayına gidebilmek için <Link> özelliğiyle sarmalayalım.

Uygulamamızın şu ana kadarki senaryosunda todoları listeleyip herhangi bir todoya tıklanınca detayına gitme işlemini gerçekleştirdik. Ancak uygulamamı ileride bir veritabanına bağlayacağım için ve buraya istek atıp gelen veriye göre işlemlerimi gerçekleştireceğim. Bu sebeple todolar listelenirken aynı zamanda her bir todonun detayı için sayfaların önceden render edilmiş hazır beklemesini istiyorum. Bunu Next.js’in sunduğu *pre-rendering* özelliği ile gerçekleştireceğim.
todos/[id]/page.tsx sayfasına gelip generateStaticParams() fonksiyonunu oluşturuyorum.

Her bir todo için bu fonksiyonu kullanmak performans açısından mantıksız görünse de, Next.js bu kodu herhangi bir sorun olmadığı konusunda iddialı :)
Artık sayfamız dinamik olmasına rağmen oluşturulan todo statik hale geldi diye düşünebiliriz. Tabi bunun için export const dynamicParams = true; kodunu da eklemeyi unutmayalım. Artık yeni bir veri eklendiğinde de *generateStaticParams()* fonksiyonumuz çalışacak.
Sıradaki işlem, yeni bir todo eklemek olacak. app/todos/create adında bir dosya ve içine de page.tsx ekliyorum. Daha sonra yeni bir todo için gereken form yapısını oluşturuyorum. Form elemanları, kullanıcı girişlerini izlemek için onChange olaylarına sahiptir ve her biri handleChange fonksiyonunu çağırır.

daha sonra handleChange fonksiyonuoluşturup , herhangi bir input alanında değişiklik olduğunda çağrıp ve input alanlarının değerlerini güncelliyorum.
AddTodo fonksiyonu ile, “Create” butonuna tıklandığında todo’nun eklenmesini başlatıyorum.

yeni bir todo eklemek için yapımız hazır ve uygulamnın son hali şekildeki gibidir.

Uygulamayı, kullanıcıya özel olarak, yani üyelik girişi yapıldığında sadece o kullanıcıya ait bir todo uygulaması olarak tasarlamak istiyorum. Bunun için, kayıt olma (sign up), giriş yapma (login) ve bu işlemlere bağlı olarak yönlendirmelerin (dashboard, kullanıcıya ait todolar gibi) bulunması gerekiyor.
App/auth adında bir klasör oluşturdum ve içine ilgili sayfaları yerleştirdim. Ancak, burada auth klasör adını parantez içinde yazarak bir gruplama yaptığımı belirtmeliyim.

Böylece, URL’de “http://.../auth/login" yerine “http://.../login" adresine doğrudan login sayfasına erişilebilecek. Aynı şekilde, todos klasörünü de bir route grubunun altına alarak dashboard’a dahil ettim. *Route group* ile, geliştiricilerin URL yolunu değiştirmeden rotaları mantıksal gruplar halinde düzenlemesine olanak tanır ve karmaşık yönlendirme sistemlerini ele almak için daha yapılandırılmış ve kolaylaştırılmış bir yaklaşım sunar. Böylece, aynı projede birlikte çalışırken sorun yaşamamızı önler.
Bu düzenlemeyle, kullanıcıya özel bir todo uygulamasının gerekli temel yapı taşlarını oluşturmuş olduk.
Fakat dashboard ve todos sayfasında kullandığımız navbarı login ve sign up sayfalarında göstermemeliyiz. *Nested layout* kullanarak bu durumu düzeltebiliriz.

Press enter or click to view image in full size

App/Layout.tsx içinde çağırdığım navbar componentimi kaldırıyorum. Ardından (dashboard) klasörümün içine layout.tsx oluşturup navbar componentimi burda çağırıyorum. Aynı işlemi (auth) klasörümün içinde de bir layout oluşturarak gerçekleştiriyorum
Hızlı bir şekilde uygulamanın metadata kısmında da değişiklik yapmak istiyorum. Metadata, web sayfalarının başlık, açıklama, anahtar kelimeler ve diğer önemli bilgileri içeren yapıdır. Bu meta veriler, sayfaların tarayıcılarda, arama sonuçlarında, sosyal medya paylaşımlarında ve diğer web hizmetlerindeki görünümünü belirler.

Uygulamamızı açıp tarayıcıdan inspect dediğimizde metadataları görebiliriz. Bu metadatalar app klasörümüzün altındaki layout.tsx sayfasında tanımlı.
Biz de gelip TodoDetail.tsx sayfamız her bir todo için dynamic metadatalar oluşturalım. Amacım her bir todo için title kısmını değişmek. Bunun için generateMetadata() fonksiyonunu kullanmam yeterli.

Bu adımdan sonra API rotası oluşturma işlemine geçebilirim. App/api/todos klasörlerini oluşturup içine route.ts dosyasını ekleyerek fonksiyonlarımı yazmaya başlıyorum. Burada, todo listeleme, ekleme, silme gibi tüm fonksiyonları tanımlayacağım.

import { NextResponse } from "next/server";

export const dynamic = "force-dynamic";

export async function GET() {
const res = await fetch("http://localhost:4000/todos");
const todos = await res.json();

return NextResponse.json(todos, {
status: 200,
});
}
export async function POST(request: any) {
const todo = await request.json();

const res = await fetch("http://localhost:4000/todos", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(todo),
});

const newTodo = await res.json();

return NextResponse.json(newTodo, {
status: 201,
});
}

Dinamik sayfalar oluşturduğumuz gibi aynı zamanda parametre alacak API’ler için de rotalar oluşturabiliriz. Bu, Next.js sayfalarında yaptığımız gibi.
Bu aşamada uygulamamızın artık hazır olduğunu söyleyebilirim. Eğer uygulamanın kimlik doğrulama işlemleri, veritabanına bağlanma süreçleri, CRUD fonksiyonları hakkında daha fazla bilgiye ihtiyacınız varsa, diğer yazılarıma göz atabilirsiniz:

Okuduğunuz için teşekkür ederim. Umarım bu yazı size faydalı olmuştur. Herhangi bir sorunuz varsa çekinmeden bana sorabilirsiniz!
https://www.linkedin.com/in/duhayildirim/

--

--

Duha Yıldırım
Duha Yıldırım

Written by Duha Yıldırım

Software engineer -my experience with the code-