React — Context API Nedir ve Nasıl Kullanılır ?

Kubilay
7 min readAug 8, 2022

Şimdi direkt olarak konuya ulaşmadan önce sadece state kullanarak bir uygulamayı nasıl kurgularız ondan sözlü olarak bahsedelim.

Öncelikle bir E-ticaret projesi geliştirdiğimizi düşünelim. Prpjemizin genel yapısı aşağıda gösterdiğim mind map ile daha anlaşılır olacaktır.

Yukarıda görselde gördüğünüz gibi bir adet ana sayfa hesabım ve sepetim sayfaları olan bir uygulamamız olduğunu düşünelim şimdi burada söyle bir senaryomuz var kullanıcı sisteme giriş yapmış mı yapmamış mı ona göre gösterilen içerikler var. Yani biraz daha detaylı bir gösterim yapmamız gerekir ise;

Gördüğünüz gibi örnek olarak Navbar için Giriş yapışmış mı yapılmamış mı bu bilgilere göre kullanıcının adını gösterdiğimiz yada Giriş yap butonunun olduğu varyasyonlar var bunlar kullanıcıdan gelen bilgilere göre şekillendireceğiz.

Kısacası kullanıcının sisteme giriş yapma durumuna göre bütün comp kendi kendilerine farklı farklı varyasyonlara giriyor. Şimdi HomePage.js olarak ana sayfamızı geliştirdiğimizi düşünelim.

Giriş yapıldığı zaman kullanıcının bilgilerinin session içinde tutulduğunu ve bu bilgilere ulaşmak için her www.sitem.com/a www.sitem.com/bawww.sitem.com/a www.sitem.com www.sitem.com/ac gibi sayfalara geçiş yapıldığı zaman bunun tekrar tekrar o sayfalarda session okunarak bilgilerin alındığını düşünelim.

Her bir sayfada bun tekrar etmek ne kadar fala kod tekrarına girer ve yorucu olur değil mi. Söyle basit ve akılda kalıcı olacağını düşündüğüm bir örnek ile başlamak istiyorum örnek ne kadar çok basit ve yapılmaması gereken bir örnek olsa da konuyu kavramak için oldukça iyi bir örnek olduğun düşünüyorum. Bu işlemi yapmak için başka başka bir çok yöntem bulabiliriz ama ben bu yöntemi tercih ettim konuyu anlatmak için. Kodu tamamen pseudocode mantığı ile normal kod yapısı arasında yazarak ilerleyelim .

Şimdi elimizde şöyle bir klasör yapısı olsun. Eğer anlatım ile beraber ilerlemek isterseniz github üzerinden linki clone yaparak benimle beraber ilerleyebilirsiniz.

Öncelikle çok basit bir yapı ile anlatım yapmaya çalışacağım mantığı kavramak için gösterdiğim state yöntemleri, fonksiyonlar ve statelerin oluşturulduğu yerler pek mantıklı gelemeyebilir ama konuyu en verimli ve en mantıklı olacak şekilde anlatmak istediğim için bu yöntemi seçtim.

Github: https://github.com/kubilaybzk/contextapi

Yukarıda gördüğünüz gibi bir NextJs ile sıfır bir proje ve görüldüğü gibi bir comp page mantığı oluşturdum.

Navbar için söyle bir yapımız var.

Projeyi ilk defa run alınca söyle bir ekran karşılayacak bizi.

Hadi beraber sağ butonları geliştirmekle başlayalım.

Alt tarafta bulunan giriş yap çıkış yap butonu ile üst tarafta bulunan butonları karıştırmayın . Alt taraf form yapmak ile konuyu uzatmak istemediğim için eklediğim iki basit button.

Şimdi User’ın giriş yaptığı bir senaryomuz olsun. Bunu biz page klasöründe bulunan index.js ile session okuyarak alabiliyoruz fakat bunu index.js içinde bulunan elemanlara iletmemiz için props olarak iletmemiz gerekiyor.

Bunun için index.js dosyamızda bulunan 
<Navbar/> kısmını
<Navbar user={user} setUser={setUser} Logout={Logout} LogIn={LogIn} />
şeklinde güncelleyelim.

console.log sayesinde objenin gelip gelmediğini kontrol ettik.

Şimdi burada önemli olan RightButtons kısmına bu bilgileri tekrar iletelim.

Şimdi RightButtons componentinin içine bu bilgileri başarı ile yolladık şimdi eğer user giriş yapmış ise nasıl görüncek giriş yapılmamış ise nasıl görünecek ayarlamalarını yapalım .

Kullanıcı giriş yapmadığı zaman gördüğü ekran
Giriş yaptığı zaman göreceği ekran .

Aynı şekilde fonksiyonlarıda buradaki butonların onclick eventlerine aktararak gerekli işlemleri yapabiliriz…
Şimdi bu fonksiyonları yada state elemanlarını başka sayfalarda yada başka yerlerde kullanmak istediğimiz zaman tekrar aynı state elemanlarını oluşturmamız aynı yöntemler ile diğer componentler içine aktarmamız gerekiyor.

Projenin genel kapsamına göre her bir component içine bu user nesnesi belkide user dışında bir çok state yada fonksiyonu yollamamız gerekecek, her bir component için props olarak yollama yöntemini uyguladığımızı düşünsenize ne kadar karmaşık ve ne kadar uğraştırıcı bir işlem.

Belkide bazı componentlerimiz şu şekil olacak.

<Example x={x} y={y} c={c} v={v} a={a} d={d} d={d} />

Yukarıda ki gibi bir componenti yönetmek ne kadar zor olur değil mi ?

Şimdi kısa bir özet geçmemiz gerekirse şimdiye kadar yaptığımız bütün işlemleri miras mantığı ile geliştirdiğimizi düşünebiliriz, yani hep bir üstteki component içinden state olarak obje yada fonksiyonları aldık .Görsel olarak şöyle göstermek daha akılda kalıcı olabilir.

Burada yaptığımız bu işleme Prop Drilling denir. Yani component ağacımızın altlarında bulunan bir child component’e props yoluyla üst componentlerden state aktarılmasıdır.

Tüm bu karmaşık kodlardan kurtulmak içinden CONTEXTAPİ kullanıyoruz.

Hazırsanız başlıyoruzzzzz.. :)

Öncelikle projemizin kök dizinine context adı verdiğimiz bir klasör oluşturalım.

Daha sonra hemen altına authenticator.js isimli bir javascript dosyası oluşturalım.

ContextApı kullanabilmemiz için import etmemiz gerekiyor. Aşağıda bulunan kod ile projemize import edelim.

import React, { useContext } from "react";
const UserContext = React.createContext();

Burada bulunan React.createContext() içine defauld olarak değerler yazabiliriz mesela bir tema context yapısı oluşturmak isteyelim sitemize giren ilk kullanıcının açık renk olan temayı görmesini istersen . React.createContext(‘light’) şeklinde tanımlamalar yapabiliriz.

ContextApi yazarken iki farklı bileşen oluşturmamız gerekiyor. Bunlar consumer ve provider olmak üzere iki farklı bileşendir.

Context.Provider

Her Context nesnesi, tüketici bileşenlerin context güncellemelerine abone olmasını sağlayan bir React Provider bileşeni ile birlikte gelir.

Provider bileşeni, bu Provider’ın soyundan gelen tüketici bileşenlerine geçirilecek olan bir value prop’unu kabul eder. Birçok tüketici bir Provider’a bağlanabilir. Provider’lar ağaçtaki daha derin değerleri değiştirmek için iç içe geçirilebilirler.

Bir Provider’ın soyundan gelen tüm tüketiciler, Provider’ın value prop’u her değiştiğinde yeniden oluşturulur. Provider’ın soyundan gelen tüketicilere (.contextType ve useContext de dahil olmak üzere) yayılması, shouldComponentUpdate metoduna tabi değildir, dolayısıyla herhangi bir bileşen güncellemeyi önlediğinde bile tüketici güncellenir.

Context.Consumer

Context değişikliklerine abone olan bir React bileşeni. Bu bileşeni kullanmak, bir fonksiyon bileşen içindeki bir context’e abone olmanıza izin verir.

Alt eleman olarak fonksiyon verilmesine ihtiyaç duyar. Fonksiyon geçerli context değerini alır ve bir React düğümü döndürür. Fonksiyona iletilen value argümanı, yukarıda bu context için ağaçta en yakın Provider’ın value prop’una eşit olacaktır. Yukarıdaki bu context için Provider yoksa, value argümanı createContext() öğesine iletilmiş defaultValue değerine eşit olur.

Yukarıda bulunan bilgiler biraz teknik gelebilir ilk öğrendiğimde bende çok anlamamıştım fakat üzerinde kendi örneğimizle ilerlediğimiz zaman kendi kendinize provider ne işe yarıyor consumer ne işe yarıyor basit bir şekilde anlayacaksınız.

Şimdi ilk olarak UserContextProvider bileşenimizi oluşturmaya başlayalım.

Not: Context yapımızı ilk kez oluştururken UserContext olarak isimlendirdiğimiz için Provider oluştururken bu ismi kullanıyoruz amacımız karmaşıklığı engellemek yoksa istediğiniz ismi verebilirsiniz.

const UserContext = React.createContext();

Yukarıda gördüğünüz çok basit bi context api yapısı burada UserContext Provider içinde state fonksiyon gibi tanımlamalarımızı yapıyoruz. UserContext.Provider içinde value değişkeni ise bu fonksiyon ve state değerlerimizi ve fonksiyonlarımızı export ettiğimiz, basitçe dışarıdan erişerek kullanmamızı sağlayan alan. ;

index.js içinde yazmış olduğumuz state ve fonksiyonlarımızı Provider içine yazalım . Daha sonra Provider içinde bunları dışarıdan erişilebilecek hale getirelim.

Daha sonra bütün componentlerimize props olarak yolladığımız değerleri silelim.

Şimdi burada yapmak istediğimiz işlem hiç miras yöntemine bulamadan istediğimiz component içinde istediğimiz şekilde bu bilgilere ulaşabilmek.

Öncelikle buna heryerden ulaşmak için bunu _app.js içinde bulunan <Component {...pageProps} /> kısmını sarmalamamız lazım çok korkunç geliyor olabilir ama yapılacak işlem çok basit.

import { UserConsumer } from "../context/authenticator";import "../styles/globals.css";function MyApp({ Component, pageProps }) {return (<UserConsumer><Component {...pageProps} /></UserConsumer>);}export default MyApp;

Gördüğünüz gibi sadece Provider ile sardık yani bütün uygulamanın en dışına provider yapısını oluşturduk bütün uygulama aslında bunun içinde çalışıyor gibi düşünebiliriz en basit anlatımı ile.

Şimdi Öncelikle index.js içinde oluşturduğumuz LogIn ve Logout fonksiyonlarımızı çağırarak butonlara bu fonksiyonlarımızı tanımlayalım.

Öncelikle index.js içine girelim ve context yapımızı import edelim.

import { UserContext } from "../context/authenticator";

Daha sonra context yapımızı kullanabilmemiz için React tarafından geliştirilen UseContext fonksiyonunu kullanalım ve fonksiyonlarımızı çağıralım (Context içinde kullandığınız isimler önemli birebir aynı olması gerekiyor import ederken ).

const UserContextDatas = useContext(UserContext);
const LogInFonkiyonu= UserContextDatas.LogIn;
const LogoutFonk= UserContextDatas.Logout;

Yukarıda gördüğünüz gibi Navbar’a hiç props yollamadık şimdi orada fonksiyonlarımızı ve user ismimizi çağırarak context yapısını ekleyelim ve projemize bi bakalım.

Giriş yap butonuna tıklayalım .

Gördüğünüz gibi projemiz çalışıyor .

Artık istediğiniz yerde her neresi olursa olsun bu yapıyı kullanarak user objesine ve fonksiyonlara erişebilirsiniz.

Elimden geldiği kadar temel bilgiler ile basit bir anlatım yapmaya çalıştım umarım bu yazımı okuyan bir geliştiriciye yardımım dokunmuştur. Teşekkür ederim.

Github :https://github.com/kubilaybzk/contextapi

--

--