React Context API nasıl kullanılır: global durum için adım adım rehber
Beceri rehberi

React Context API nasıl kullanılır: global durum için adım adım rehber

Hazırlayan: Mindset Institute EditörlüğüGüncellendi: 5 dk okuma

createContext, sağlayıcı ve useContext ile paylaşılan durumu yönetmek; özel hook kalıbı, gereksiz render sorunu ve context yetmediğinde alternatifler.

Context hangi sorunu çözer?

React'te veri, props ile yukarıdan aşağı akar. Uygulama büyüdükçe oturum açmış kullanıcı, tema ya da dil seçimi gibi birçok bileşenin ihtiyaç duyduğu bir değeri araya giren her bileşenden geçirmek gerekir. Buna prop drilling denir: ortadaki bileşenler değeri kullanmadığı hâlde yalnızca iletmek için prop taşır.

Context API bu değeri ağacın üstünde bir kez sağlayıp altındaki herhangi bir bileşenin doğrudan okumasına izin verir. Ancak her paylaşılan değer için context açmak yanlıştır. Önce şu alternatiflere bakın: bileşen kompozisyonu (children ile alt ağacı dışarıdan vermek) ve durumu gerçekten gereken en yakın ortak üst bileşende tutmak. Prop drilling'in tek veya az sayıda katmanda olduğu durumlarda düz prop genellikle daha okunaklıdır.

Adım adım: createContext, provider ve useContext

Tema örneğiyle adımlar:

  • Context nesnesini oluşturun:

import { createContext } from "react"; export const TemaContext = createContext("acik");

  • Üst bileşende değeri sağlayın. Güncellenebilir olması için durumla birlikte kullanılır:

function Uygulama() { const [tema, setTema] = useState("acik"); return ( <TemaContext value={{ tema, setTema }}> <Sayfa /> </TemaContext> ); }

  • Altındaki herhangi bir bileşende okuyun:

const { tema, setTema } = useContext(TemaContext);

React belgesinde sağlayıcı olarak context nesnesinin kendisi kullanılır. Daha eski kod ve sürümlerde aynısı TemaContext.Provider biçiminde yazılır; projenizin React sürümüne göre hangisinin desteklendiğini kontrol edin.

createContext'e verilen varsayılan değer yalnızca üstte hiç sağlayıcı yoksa kullanılır ve kendiliğinden değişmez. Değerin değişmesi için durumla (useState ya da useReducer) birlikte kullanılması gerekir. Sağlayıcıda value vermeyi unutursanız altındaki bileşenler varsayılanı değil undefined alır.

Özel hook ile güvenli kullanım

useContext'i her bileşende doğrudan çağırmak yerine bir özel hook ile sarmak birkaç yarar sağlar: bileşenler context nesnesini bilmek zorunda kalmaz ve sağlayıcı olmadan kullanım hatası açık bir mesajla yakalanır.

export function useTema() { const baglam = useContext(TemaContext); if (baglam === undefined) { throw new Error("useTema, TemaSaglayici içinde kullanılmalı"); } return baglam; }

Bu kalıpta context varsayılan değeri undefined bırakılır. Ayrıca sağlayıcı bileşeni (TemaSaglayici) durum mantığıyla birlikte ayrı bir dosyaya alınır; uygulama kökü sade kalır, test sırasında sağlayıcı kolayca değiştirilir.

Oturum örneğinde aynı yapı kullanılır: SaglayiciKullanici durumu tutar, useKullanici hook'u hem kullanıcıyı hem giriş ve çıkış fonksiyonlarını verir. Bileşenler kimlik doğrulamanın nasıl yapıldığını bilmez, yalnızca sonucu okur.

Performans: değer değişince kim yeniden render olur?

Sağlayıcının value'su React'in Object.is karşılaştırmasıyla değiştiyse, o context'i okuyan tüm bileşenler yeniden render edilir. memo ile sarılmış olsalar bile context değişimi onları atlatmaz.

En sık hata, sağlayıcıya her render'da yeni bir nesne vermektir: value={{ tema, setTema }}. Sağlayıcıyı içeren bileşen her render olduğunda nesne yeniden oluşur ve tüm okuyucular, içerik değişmemiş olsa bile yeniden render olur. Çözüm değeri sabitlemektir: nesneyi useMemo, fonksiyonları useCallback ile üretin ve bağımlılıkları doğru yazın. React belgesi bunu bir performans iyileştirmesi olarak sunar, doğruluk için şart değildir; sağlayıcı sık render oluyorsa ya da altındaki ağaç büyükse devreye alın.

Diğer yol context'i bölmektir: sık değişen ve nadir değişen değerleri ayrı context'lere koyun. Örneğin durumu okuyan ve yalnızca fonksiyonu kullanan bileşenler için durum ile dispatch'i ayrı context'lerde sağlamak, yalnızca eylem tetikleyen bileşenlerin gereksiz render'ını önler.

Örnek: sepet durumunu useReducer ve context ile paylaşmak

Örneğin bir mağaza arayüzünde sepet, başlıktaki rozet, ürün kartı ve ödeme sayfasında okunuyor olsun. Güncelleme kurallarını tek yerde toplamak için useReducer, paylaşım için context kullanılır:

function sepetIndirgeyici(sepet, eylem) { switch (eylem.tur) { case "ekle": return [...sepet, eylem.product]; case "cikar": return sepet.filter(u => u.id !== eylem.id); default: throw new Error("Bilinmeyen eylem"); } }

Sağlayıcıda durum ve dispatch ayrı context'lerle verilir:

const SepetContext = createContext(null); const SepetEylemContext = createContext(null);

function SepetSaglayici({ children }) { const [sepet, dispatch] = useReducer(sepetIndirgeyici, []); return ( <SepetContext value={sepet}> <SepetEylemContext value={dispatch}>{children}</SepetEylemContext> </SepetContext> ); }

Dispatch referansı React tarafından sabit tutulduğu için yalnızca "sepete ekle" düğmesi içeren ürün kartları, sepet içeriği değiştiğinde yeniden render olmaz; yalnızca rozet ve ödeme sayfası sepeti okur. Eylem türlerini tek bir dosyada tutmak, yeni geliştiricinin durumun nasıl değiştiğini bir bakışta görmesini sağlar.

Context ne zaman yetmez?

Context bir durum yönetim kütüphanesi değildir; yalnızca değeri ağaca taşır. Şu durumlarda başka araç gerekir:

  • Çok sık güncellenen değerler: fare konumu, form girdisi gibi hızlı değişen değerleri context'e koymak büyük alt ağacı sürekli render ettirir.
  • Sunucudan gelen veri: önbellekleme, yeniden doğrulama ve yükleniyor durumu için bir veri çekme kütüphanesi daha uygundur.
  • Karmaşık güncelleme mantığı: useReducer ile context birlikte kullanılabilir; olay türlerine göre tek yerde güncelleme yapılır.
  • Çok sayıda bağımsız parça ve ince taneli abonelik: harici bir durum kütüphanesi değerlendirilebilir.

Karar ölçütü basittir: değer nadir değişiyor ve ağacın geniş bir kısmı tarafından okunuyorsa (tema, dil, oturum) context uygundur. Sık değişiyor ve az sayıda bileşen okuyorsa durumu yakında tutun.

Sık yapılan hatalar

  • Her paylaşılan değer için ayrı context açıp sağlayıcı yığını oluşturmak.
  • Sağlayıcıyı okuyucu bileşenin içine koymak: useContext her zaman kendi üstündeki en yakın sağlayıcıyı arar, kendi bileşeninin içindekini görmez.
  • value'ya her render'da yeni nesne vermek.
  • Hızlı değişen değeri context'e koymak.
  • Varsayılan değerin güncellenebileceğini sanmak.
  • Paketleme sırasında aynı context nesnesinin birden fazla kopyasının oluşması; sağlayıcı ve okuyucu aynı nesneyi kullanmalıdır.

Bu beceriyi Mindset programlarında nerede çalışırsınız?

Modern Web Geliştirme, Frontend (React) programındaki "Global State Yönetimi" modülü context ile paylaşılan durumu işler. React İleri Seviye: Performans ve Durum Yönetimi programı ise "Context ve Durum Yönetimi Mimarisi" ve "Memoization ve Referans Kararlılığı" modülleriyle context'in render maliyetini ve doğru sınırlarını ele alır.

Uygulamanın büyümesiyle durum yapısı karmaşıklaşan ön yüz ekipleri ve kod tabanında ortak bir durum yönetim yaklaşımı oluşturmak isteyen teknik liderler için uygundur. Kurumsal ekiplerde context kullanım kurallarının birlikte belirlenmesi, kod incelemelerinde tekrar eden tartışmaları azaltır.

İlgili Mindset programı

Modern Web Geliştirme — Frontend (React)

Sık sorulanlar

Sık sorulan sorular

Context API ile Redux arasındaki fark nedir?

Context, değeri ağaç boyunca taşıyan bir React mekanizmasıdır; durum güncelleme kuralları, geliştirici araçları ve ince taneli abonelik sunmaz. Redux gibi kütüphaneler bunları ekler. Küçük ve nadir değişen paylaşılan durum için context yeterli olabilir; büyük ve sık değişen durum için kütüphane değerlendirilir.

Birden fazla context kullanabilir miyim?

Evet. Tema, dil ve oturum gibi birbirinden bağımsız değerler için ayrı context açmak ve sağlayıcıları iç içe koymak yaygın bir yöntemdir. Sağlayıcılar çoğalırsa bunları tek bir bileşende toplamak okunabilirliği artırır. Birbiriyle çok ilişkili değerleri tek context'te tutmak ise gereksiz render'a yol açabilir.

useContext kullanan bileşen neden her seferinde render oluyor?

Sağlayıcının value'su her render'da yeni bir nesne ya da fonksiyon olarak üretiliyor olabilir. React yeni referansı değişim sayar ve tüm okuyucuları yeniden render eder. Değeri useMemo ve useCallback ile sabitleyin ya da context'i sık ve nadir değişenler olarak bölün.

Context içindeki durumu nasıl test ederim?

Bileşeni test ederken gerçek sağlayıcıyı sarmalayıcı olarak kullanın ya da test için basit bir değerle özel bir sağlayıcı üretin. Özel hook ve sağlayıcının ayrı dosyada olması testi kolaylaştırır; bileşenin davranışını sağlayıcıdan gelen farklı değerlerle deneyin.

React Context API ile Global Durum Yönetimi