SolidStart Hooks’a Giriş: Reaktif ve Verimli Web Uygulamaları Geliştirme
SolidStart, modern web uygulamaları geliştirmek için SolidJS üzerine inşa edilmiş güçlü bir meta-çerçevedir. React, Vue veya Angular gibi diğer popüler çerçevelerden farklı olarak, SolidJS’in reaktif doğası, bileşenlerin yalnızca değişen kısımlarının güncellenmesini sağlayarak üstün performans sunar. Bu makalede, SolidStart’ın kalbinde yer alan ve uygulamalarınızı daha verimli, yönetilebilir ve güçlü hale getiren “hooks” kavramını detaylı bir şekilde inceleyeceğiz. SolidStart’ın sunduğu reaktif primitiflerden özel entegrasyonlara kadar her yönüyle hooks dünyasına dalacağız.
SolidStart ve SolidJS’in Temelleri
Modern web geliştirme dünyasında performans, geliştirici deneyimi ve ölçeklenebilirlik, bir çerçeve seçiminde kilit rol oynar. SolidStart, bu ihtiyaçları karşılamak üzere SolidJS’in üzerine inşa edilmiş, tam özellikli bir meta-çerçevedir.
SolidJS Nedir? Reaktifliği Anlamak
SolidJS, deklaratif ve reaktif bir JavaScript kütüphanesidir. React’e benzer bir JSX sözdizimi kullanmasına rağmen, temel çalışma prensibi oldukça farklıdır. SolidJS, sanal DOM kullanmak yerine, doğrudan gerçek DOM üzerinde çalışır ve ince taneli (fine-grained) reaktiviteye odaklanır. Bu, bir durum değiştiğinde, sadece o duruma bağlı olan DOM parçalarının güncellendiği anlamına gelir. Sonuç olarak, gereksiz yeniden oluşturmalar (re-renders) ortadan kalkar ve olağanüstü performans elde edilir.
SolidJS’in reaktivite modeli, sinyaller (signals), efektler (effects) ve memolar (memos) gibi primitifler üzerine kuruludur. Bu primitifler, uygulamanızdaki veri akışını ve yan etkileri deklaratif bir şekilde yönetmenizi sağlar.
SolidStart’ın Rolü: Meta-Çerçeve Avantajları
SolidJS harika bir UI kütüphanesi olsa da, bir web uygulamasının tüm ihtiyaçlarını tek başına karşılamaz. Rota yönetimi, sunucu tarafı render (SSR), statik site oluşturma (SSG), veri çekme ve API entegrasyonları gibi konularda ek çözümlere ihtiyaç duyulur. İşte SolidStart tam da bu noktada devreye girer.
SolidStart, SolidJS’i temel alarak, yukarıda bahsedilen tüm bu özellikleri tek bir çatı altında toplayan bir meta-çerçevedir. Next.js veya Nuxt.js gibi diğer popüler meta-çerçevelere benzer şekilde, dosya tabanlı yönlendirme, veri yükleyiciler ve sunucu eylemleri gibi özellikler sunar. Bu, geliştiricilerin sadece UI bileşenlerine odaklanmasını sağlarken, altyapısal karmaşıklığı SolidStart’ın yönetmesine olanak tanır.
Neden SolidStart Hooks Kullanmalıyız?
Hooks, SolidJS ve SolidStart’ta reaktif mantığı bileşenlerinizle entegre etmenin standart yoludur. Durum yönetimi, yan etkileri işleme, hesaplanmış değerleri optimize etme ve SolidStart’ın özel özelliklerine erişme gibi görevler için hooks kullanılır. Hooks kullanarak:
- Bileşenler arası mantık paylaşımını kolaylaştırırsınız.
- Kodunuzu daha okunabilir ve bakımı yapılabilir hale getirirsiniz.
- SolidJS’in ince taneli reaktivite modelinden tam olarak faydalanırsınız.
- SolidStart’ın sunduğu gelişmiş özelliklere (veri çekme, yönlendirme vb.) erişirsiniz.
SolidStart Hooks’a Genel Bakış
Hooks, fonksiyonel bileşenler içinde reaktif mantığı kullanmamızı sağlayan özel fonksiyonlardır. SolidStart’ta hooks, SolidJS’in temel reaktivite primitiflerini ve SolidStart’ın kendi ek özelliklerini bir araya getirir.
Hooks Nedir ve Ne İşe Yarar?
Hooks, SolidJS’in reaktivite primitiflerini (sinyaller, efektler, memolar) ve bileşen yaşam döngüsü yönetimini fonksiyonel bileşenler içinde kullanmamızı sağlayan fonksiyonlardır. React’teki hooks’a benzer bir kavram olsa da, SolidJS’in derleme zamanı reaktivitesi sayesinde farklı bir çalışma prensibine sahiptir. Hooks sayesinde, durumu yönetebilir, yan etkileri (veri çekme, DOM manipülasyonu) gerçekleştirebilir ve bileşenler arası tekrar kullanılabilir mantık parçaları oluşturabiliriz.
Temel SolidJS Reaktivite Primitifleri: Sinyaller, Efektler, Memolar
SolidJS’in reaktivite modelinin temel taşları olan bu primitifler, SolidStart hooks’unun da temelini oluşturur:
- Sinyaller (
createSignal): Değişebilir bir değeri ve bu değer değiştiğinde bağımlı olan her şeyi otomatik olarak güncelleyen bir mekanizma sağlar. - Efektler (
createEffect): Bir veya daha fazla reaktif bağımlılık değiştiğinde belirli bir yan etkiyi (konsola yazdırma, API çağrısı yapma vb.) çalıştırmak için kullanılır. - Memolar (
createMemo): Bir veya daha fazla reaktif bağımlılığa dayalı olarak hesaplanmış bir değeri önbelleğe alır. Bağımlılıklar değişmediği sürece hesaplama yeniden yapılmaz, bu da performansı artırır.
SolidStart’ın Sağladığı Ek Hooks
SolidStart, SolidJS’in temel primitiflerine ek olarak, kendi meta-çerçeve özelliklerini kullanmamızı sağlayan bir dizi özel hook sunar. Bunlar genellikle yönlendirme, veri çekme ve sunucu etkileşimleri gibi alanlarda kullanılır. Örneğin, useParams ile URL parametrelerine erişebilir, useRouteData ile sunucu tarafından yüklenmiş verilere ulaşabiliriz.
Temel Reaktivite Hooks’ları
SolidJS’in kalbinde yatan ve SolidStart uygulamalarınızın temelini oluşturan reaktivite primitiflerini ve bunların hook versiyonlarını daha yakından inceleyelim.
createSignal: Durum Yönetiminin Kalbi
createSignal, SolidJS’te reaktif durum oluşturmanın en temel yoludur. Bir getter (okuyucu) ve bir setter (yazıcı) fonksiyonu döndürür. Getter’ı çağırdığınızda mevcut değeri alırsınız ve setter’ı çağırdığınızda değeri güncellersiniz.
import { createSignal } from "solid-js";
function Counter() {
const [count, setCount] = createSignal(0);
return (
Sayım: {count()}
);
}
Yukarıdaki örnekte, count() değeri değiştiğinde, sadece
etiketi içindeki metin güncellenir, tüm bileşen yeniden oluşturulmaz. Bu, SolidJS'in ince taneli reaktivitesinin gücünü gösterir.
createEffect: Yan Etkileri Yönetme
createEffect, bir veya daha fazla reaktif bağımlılık değiştiğinde belirli bir yan etkiyi (side effect) çalıştırmak için kullanılır. Örneğin, konsola bir mesaj yazdırmak, bir API çağrısı yapmak veya DOM'u doğrudan manipüle etmek için idealdir.
import { createSignal, createEffect } from "solid-js";
function UserProfile() {
const [userId, setUserId] = createSignal(1);
const [userName, setUserName] = createSignal("Yükleniyor...");
createEffect(() => {
// userId değiştiğinde bu blok çalışır
console.log(Kullanıcı ID değişti: ${userId()});
// Gerçek bir uygulamada burada bir API çağrısı yapardık
fetch(/api/users/${userId()})
.then(res => res.json())
.then(data => setUserName(data.name));
});
return (
Kullanıcı Adı: {userName()}
);
}
createEffect içindeki kod, userId() sinyali her değiştiğinde yeniden çalışır. Bu, veri çekme gibi işlemleri reaktif bir şekilde yönetmenizi sağlar.
createMemo: Hesaplanan Değerleri Optimize Etme
createMemo, pahalı hesaplamaları önbelleğe almak ve yalnızca bağımlılıkları değiştiğinde yeniden hesaplamak için kullanılır. Bu, uygulamanızın performansını önemli ölçüde artırabilir.
import { createSignal, createMemo } from "solid-js";
function ProductDisplay() {
const [price, setPrice] = createSignal(100);
const [quantity, setQuantity] = createSignal(2);
const totalPrice = createMemo(() => {
console.log("Toplam fiyat hesaplanıyor..."); // Sadece bağımlılıklar değiştiğinde çalışır
return price() * quantity();
});
return (
Fiyat: {price()}
Miktar: {quantity()}
Toplam Fiyat: {totalPrice()}
);
}
totalPrice memo'su, yalnızca price veya quantity sinyallerinden biri değiştiğinde yeniden hesaplanır. Bu, gereksiz hesaplamaları önler.
onCleanup: Kaynakları Serbest Bırakma
onCleanup, bir reaktif kapsam (scope) sona erdiğinde (örneğin, bir bileşen DOM'dan kaldırıldığında veya bir efekt yeniden çalıştığında) temizleme işlemleri yapmak için kullanılır. Bu, bellek sızıntılarını önlemek ve kaynakları düzgün bir şekilde serbest bırakmak için önemlidir.
import { createEffect, onCleanup } from "solid-js";
function Timer() {
createEffect(() => {
const interval = setInterval(() => {
console.log("Zamanlayıcı çalışıyor...");
}, 1000);
onCleanup(() => {
clearInterval(interval); // Bileşen kaldırıldığında interval'i temizle
console.log("Zamanlayıcı temizlendi.");
});
});
return Zamanlayıcı aktif.
;
}
SolidStart'a Özel Hooks'lar ve Entegrasyonlar
SolidStart, SolidJS'in temel reaktivite primitiflerine ek olarak, meta-çerçeve özelliklerini kullanmamızı sağlayan bir dizi özel hook sunar. Bu hooks, yönlendirme, veri çekme ve sunucu etkileşimleri gibi alanlarda geliştirici deneyimini zenginleştirir.
useParams ve useSearchParams: Rota Parametrelerini Yönetme
SolidStart'ın dosya tabanlı yönlendirme sistemiyle entegre olan bu hooks, URL'deki dinamik parametrelere ve sorgu dizisi parametrelerine erişmenizi sağlar.
useParams(): Dinamik rota segmentlerindeki değerleri bir obje olarak döndürür (örneğin,/users/:idiçiniddeğeri).useSearchParams(): URL'nin sorgu dizisindeki (query string) parametreleri birURLSearchParamsobjesi olarak döndürür.
import { useParams, useSearchParams } from "@solidjs/router";
function UserDetail() {
const params = useParams(); // Örn: { id: "123" }
const [searchParams, setSearchParams] = useSearchParams(); // Örn: { tab: "profile" }
return (
Kullanıcı ID: {params.id}
Aktif Sekme: {searchParams.tab || "Genel"}
);
}
useNavigate: Programatik Navigasyon
useNavigate hook'u, kullanıcıları bir butona tıklama veya bir form gönderimi gibi olaylar sonucunda programatik olarak farklı rotalara yönlendirmek için kullanılır.
import { useNavigate } from "@solidjs/router";
function Dashboard() {
const navigate = useNavigate();
const goToSettings = () => {
navigate("/settings", { replace: true }); // Geçmişi değiştirmeden yönlendir
};
return (
Kontrol Paneli
);
}
useRouteData: Sunucu Tarafından Veri Çekme
SolidStart'ın en güçlü özelliklerinden biri, sunucu tarafında veri çekme yeteneğidir. useRouteData hook'u, bir rotanın routeData fonksiyonu tarafından sağlanan verilere erişmenizi sağlar. Bu, sayfanızın render edilmeden önce gerekli verilerin hazır olmasını garantiler.
// src/routes/users/[id].tsx
import { useRouteData } from "@solidjs/router";
import { createServerData$ } from "solid-start/server";
export function routeData({ params }) {
return createServerData$(async ([, id]) => {
const res = await fetch(https://api.example.com/users/${id});
return res.json();
}, { key: () => ["users", params.id] });
}
function UserPage() {
const user = useRouteData();
return (
Kullanıcı Detayı
Ad: {user()?.name}
Email: {user()?.email}
);
}
routeData fonksiyonu, bileşen render edilmeden önce sunucuda çalışır ve veriyi çeker. useRouteData ise bu veriye bileşen içinde reaktif bir sinyal olarak erişmenizi sağlar.
createServerAction ve createServerMultiAction: Sunucu İşlemleri
SolidStart, form gönderimleri veya diğer kullanıcı etkileşimleri aracılığıyla sunucu tarafında kod çalıştırmak için createServerAction ve createServerMultiAction hooks'larını sunar. Bu, API endpoint'leri oluşturmaya gerek kalmadan doğrudan sunucu kodunu çağırabilmenizi sağlar.
// src/routes/contact.tsx
import { createServerAction$, createServerMultiAction$ } from "solid-start/server";
// Tek bir işlem için
const sendContactForm = createServerAction$(async (form: FormData, { request }) => {
const name = form.get("name");
const email = form.get("email");
const message = form.get("message");
console.log(Sunucuda form gönderildi: ${name}, ${email}, ${message});
// Burada veritabanına kaydetme, e-posta gönderme gibi işlemler yapılabilir.
return { success: true, message: "Mesajınız alındı!" };
});
function ContactPage() {
const [sending, { Form }] = sendContactForm();
return (
Bize Ulaşın
{sending.result && {sending.result.message}
}
);
}
Bu hooks, istemci ve sunucu arasındaki etkileşimi basitleştirir ve tam yığın (full-stack) geliştirme deneyimini iyileştirir.
Özel (Custom) Hooks Oluşturma
SolidJS ve SolidStart'ın gücü, kendi özel hooks'larınızı oluşturarak tekrar kullanılabilir ve soyutlanmış mantık parçaları yaratabilmenizden gelir. Bu, kodunuzu daha modüler ve yönetilebilir hale getirir.
Neden Özel Hooks Kullanmalıyız?
Özel hooks, bileşenler arasında durum bilgisi olan mantığı yeniden kullanmanın harika bir yoludur. Örneğin, bir API'den veri çekme, bir formun durumunu yönetme veya bir zamanlayıcıyı kontrol etme gibi karmaşık mantıkları tek bir fonksiyonda toplayabilirsiniz. Bu sayede:
- Kod tekrarını azaltırsınız.
- Mantığı bileşenlerden ayırarak daha temiz bileşenler elde edersiniz.
- Test edilebilirliği artırırsınız.
- Uygulamanızın farklı yerlerinde aynı mantığı tutarlı bir şekilde kullanırsınız.
Basit Bir Özel Hook Örneği
Basit bir sayaç mantığını özel bir hook olarak nasıl oluşturacağımıza bakalım:
// src/hooks/useCounter.ts
import { createSignal } from "solid-js";
function useCounter(initialValue = 0) {
const [count, setCount] = createSignal(initialValue);
const increment = () => setCount(count() + 1);
const decrement = () => setCount(count() - 1);
const reset = () => setCount(initialValue);
return { count, increment, decrement, reset };
}
// src/components/MyComponent.tsx
import { useCounter } from "../hooks/useCounter";
function MyComponent() {
const { count, increment, decrement, reset } = useCounter(10);
return (
Mevcut Sayım: {count()}
);
}
useCounter hook'u, sayaç mantığını soyutlar ve herhangi bir bileşen tarafından kolayca kullanılabilir hale getirir.
İleri Düzey Özel Hook Tasarımı
Daha karmaşık senaryolarda, özel hooks'larınız içinde birden fazla SolidJS primitifi (createSignal, createEffect, createMemo) kullanabilir ve hatta diğer hooks'ları çağırabilirsiniz. Örneğin, bir API'den veri çeken ve yükleme/hata durumlarını yöneten bir hook oluşturabilirsiniz.
// src/hooks/useFetch.ts
import { createSignal, createEffect } from "solid-js";
function useFetch(url: () => string) {
const [data, setData] = createSignal(null);
const [loading, setLoading] = createSignal(true);
const [error, setError] = createSignal(null);
createEffect(() => {
setLoading(true);
setError(null);
setData(null); // Veriyi sıfırla
const currentUrl = url();
if (!currentUrl) {
setLoading(false);
return;
}
fetch(currentUrl)
.then((res) => {
if (!res.ok) throw new Error(res.statusText);
return res.json();
})
.then((json) => setData(json))
.catch((err) => setError(err))
.finally(() => setLoading(false));
});
return { data, loading, error };
}
// src/components/PostList.tsx
import { createSignal } from "solid-js";
import { useFetch } from "../hooks/useFetch";
interface Post {
id: number;
title: string;
body: string;
}
function PostList() {
const [postId, setPostId] = createSignal(1);
const { data: post, loading, error } = useFetch(() => https://jsonplaceholder.typicode.com/posts/${postId()});
return (
Gönderi Detayı
{loading() && Yükleniyor...
}
{error() && Hata: {error()?.message}
}
{post() && (
{post()?.title}
{post()?.body}
)}
);
}
Bu useFetch hook'u, dinamik bir URL'ye bağlı olarak veri çeker ve yükleme/hata durumlarını yönetir. Bu, SolidStart uygulamalarında karmaşık veri çekme mantığını temiz bir şekilde soyutlamak için güçlü bir örnektir.
Performans ve En İyi Uygulamalar
SolidStart ve SolidJS, doğası gereği yüksek performans sunsa da, hooks'ları doğru kullanarak bu performansı daha da optimize edebilir ve uygulamanızın bakımını kolaylaştırabilirsiniz.
Reaktiviteyi Doğru Kullanmak
SolidJS'in ince taneli reaktivitesi, sadece değişen kısımların güncellenmesini sağlar. Bu avantajdan tam olarak yararlanmak için:
- Sinyalleri küçük ve odaklı tutun: Mümkün olduğunca küçük veri parçalarını sinyal olarak tanımlayın. Büyük bir obje yerine, objenin içindeki her bir özelliği ayrı bir sinyal olarak yönetmek daha verimli olabilir.
- Sinyal değerlerine doğrudan erişmeyin: Sinyal getter'larını (örneğin,
count()) yalnızca reaktif kapsamlar (JSX,createEffect,createMemo) içinde çağırın. Fonksiyon dışındaki bir yerde çağırırsanız reaktiviteyi kaybedersiniz. createMemo'yu pahalı hesaplamalar için kullanın: Bir değer birden fazla reaktif bağımlılığa dayanıyorsa ve hesaplaması maliyetliyse,createMemokullanarak bu hesaplamayı önbelleğe alın.
Gereksiz Yeniden Oluşturmaları Önlemek
SolidJS, React'in sanal DOM tabanlı yeniden oluşturma modelinden farklı çalıştığı için "gereksiz yeniden oluşturma" kavramı SolidJS'te biraz farklıdır. SolidJS'te bileşenler genellikle bir kez çalışır ve reaktif güncellemeler doğrudan DOM'a uygulanır. Ancak, bazı durumlar yine de performansı etkileyebilir:
- Sinyal güncellemelerini optimize edin: Bir sinyali aynı değerle tekrar tekrar güncellemekten kaçının.
- Döngü içinde reaktif bağımlılıklar: Bir
fordöngüsü içinde her iterasyonda yeni bir sinyal veya efekt oluşturmaktan kaçının, bu performansı düşürebilir. - JSX içinde gereksiz fonksiyon çağrıları: JSX içinde her render'da yeniden oluşturulan anonim fonksiyonlar yerine, bileşen dışında tanımlanmış sabit fonksiyonları veya
createMemokullanın.
Kod Düzenliliği ve Bakım
Uygulamanız büyüdükçe, hooks'larınızın düzenli ve bakımı yapılabilir olması önemlidir:
- Özel hooks kullanın: Karmaşık veya tekrar eden mantıkları özel hooks'lara soyutlayın. Bu, bileşenlerinizi daha temiz tutar ve mantığı daha kolay test etmenizi sağlar.
- Hooks'ları bileşenlerin başında tanımlayın: Hooks'ları her zaman fonksiyonel bileşenlerinizin veya diğer hooks'larınızın en üst seviyesinde çağırın. Koşullu olarak (
ifiçinde) veya döngü içinde çağırmaktan kaçının. - Anlamlı isimlendirme: Hooks'larınıza ve sinyallerinize açıklayıcı isimler verin. Örneğin,
useUserAuthveyacreateTodoItem.
Sonuç
SolidStart Hooks, SolidJS'in ince taneli reaktivite modelini kullanarak modern, performanslı ve bakımı kolay web uygulamaları geliştirmenin temel taşıdır. createSignal ile durumu yönetmekten, createEffect ile yan etkileri kontrol etmeye, createMemo ile hesaplamaları optimize etmeye ve SolidStart'ın özel hooks'ları ile yönlendirme ve sunucu etkileşimlerini sağlamaya kadar geniş bir yelpazede çözümler sunar.
Özel hooks oluşturma yeteneği sayesinde, uygulamanızın mantığını modüler parçalara ayırabilir, kod tekrarını azaltabilir ve daha ölçeklenebilir bir yapı kurabilirsiniz. SolidStart'ın sunduğu bu güçlü araç setiyle, hem geliştirici deneyiminden ödün vermeden hem de son kullanıcıya olağanüstü hızlı uygulamalar sunarak web geliştirme potansiyelinizi maksimize edebilirsiniz. SolidStart ve hooks'larını benimseyerek, geleceğin reaktif web uygulamalarını inşa etmeye hazırsınız.
SSS (Sık Sorulan Sorular)
- SolidStart Hooks ile React Hooks arasındaki temel fark nedir?
- SolidStart Hooks (SolidJS'ten miras aldığı gibi), React'in sanal DOM ve yeniden oluşturma modelinden farklı olarak, ince taneli reaktiviteye dayanır. SolidJS'te bileşenler genellikle bir kez çalışır ve reaktif güncellemeler doğrudan DOM'a uygulanır, bu da gereksiz yeniden oluşturmaları ortadan kaldırır. React'te ise hooks, bileşenlerin yeniden oluşturulması sırasında durumun korunmasını sağlar.
- Hangi durumlarda
createMemoyerinecreateEffectkullanmalıyım? createMemo, bir veya daha fazla reaktif bağımlılığa dayalı olarak bir değer hesaplamanız ve bu değeri önbelleğe almanız gerektiğinde kullanılır.createEffectise, bir veya daha fazla reaktif bağımlılık değiştiğinde bir yan etki (konsola yazdırma, API çağrısı, DOM manipülasyonu vb.) gerçekleştirmeniz gerektiğinde kullanılır. Yani, bir değer üretmek içincreateMemo, bir eylem gerçekleştirmek içincreateEffect.- SolidStart'ta özel (custom) hook oluşturmak ne gibi avantajlar sağlar?
- Özel hooks, tekrar kullanılabilir mantık parçalarını bileşenlerinizden soyutlamanıza olanak tanır. Bu, kod tekrarını azaltır, bileşenlerinizi daha temiz ve okunabilir hale getirir, mantığın daha kolay test edilmesini sağlar ve uygulamanızın farklı yerlerinde tutarlı bir şekilde aynı mantığı kullanmanıza yardımcı olur.
useRouteDatane zaman kullanılır ve nasıl çalışır?useRouteData, SolidStart'ın sunucu tarafı veri çekme özelliğini kullanmak için tasarlanmıştır. Bir rotanınrouteDatafonksiyon