React'in Context API'sine Giriş

Yayınlanan: 2022-03-10
Kısa özet ↬ Bu makalede, React uygulamalarınızdaki global uygulama durumlarını sahne detaylandırmasına başvurmadan yönetmenize olanak tanıyan React'in Context API'sini nasıl kullanacağınızı öğreneceksiniz.

Bu eğitim için, kancalar hakkında adil bir anlayışa sahip olmalısınız. Yine de, başlamadan önce, bu makalede ne olduklarını ve kullanacağımız kancaları kısaca tartışacağım.

React Dokümanlarına göre:

Kancalar , React 16.8'deki yeni bir eklentidir. Bir sınıf yazmadan durum ve diğer React özelliklerini kullanmanıza izin veriyorlar.”

Temel olarak bir React kancası budur. İşlevsel bileşenlerimizde durum, referanslar ve diğer React özelliklerini kullanmamıza olanak tanır.

Bu yazıda karşılaşacağımız iki kancayı tartışalım.

useState Kancası

useState kancası , durumu işlevsel bileşenlerimizde kullanmamıza izin verir . useState kancası, durumumuzun ilk değerini tek argüman olarak alır ve iki elemanlı bir dizi döndürür. İlk eleman durum değişkenimizdir ve ikinci eleman durum değişkeninin değerini güncellemeyi kullanabileceğimiz bir fonksiyondur.

Aşağıdaki örneğe bir göz atalım:

 import React, {useState} from "react"; function SampleComponent(){ const [count, setCount] = useState(0); }

Burada count bizim durum değişkenimizdir ve başlangıç ​​değeri 0 iken setCount , count değerini güncellemek için kullanabileceğimiz bir fonksiyondur.

useContext Hook

Bunu makalede daha sonra tartışacağım ama bu kanca temelde bir bağlamın değerini tüketmemize izin veriyor . Bunun gerçekte ne anlama geldiği makalenin ilerleyen bölümlerinde daha belirgin hale gelecektir.

İplik Çalışma Alanları

Yarn çalışma alanları, monolitik bir depo (monorepo) kullanarak proje kod tabanınızı düzenlemenize izin verir. React, monorepo olan ve bu amaca ulaşmak için Yarn çalışma alanlarını kullanan açık kaynaklı bir projenin güzel bir örneğidir. İlgili bir makaleyi okuyun →

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Neden Bağlam API'sine İhtiyacımız Var?

React uygulamamız için açık mod ve karanlık mod arasında geçiş yapan bir "tema değiştirici" bileşeni oluşturmak istiyoruz. Her bileşenin mevcut tema moduna erişimi olması gerekir, böylece uygun şekilde şekillendirilebilirler.

Normalde, aksesuarlar aracılığıyla tüm bileşenlere mevcut tema modunu sağlar ve mevcut temayı state kullanarak güncellerdik:

 import React from "react"; import ReactDOM from "react-dom"; function App() { return ( <div> <Text theme= "blue" /> <h1>{theme}</h1> </div> ); } function Text({theme}) { return( <h1 style = {{ color: `${theme}` }}>{theme}</h1> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);

Yukarıdaki kod örneğinde, bir h1 öğesi oluşturan bir Metin Bileşeni oluşturduk. h1 öğesinin rengi mevcut tema moduna bağlıdır. Şu anda, tema mavidir. state kullanarak blue ve red temalar arasında geçiş yapabiliriz.

useState kancasını kullanarak “theme” adında bir durum oluşturacağız. useState kancası, temanın geçerli değerini ve temayı güncellemek için kullanabileceğimiz bir işlevi döndürür.

O halde tema durumumuzu oluşturalım:

 const [theme, setTheme] = React.useState("blue");

Ayrıca App bileşenimize bir düğme öğesi ekleyeceğiz. Bu düğme temaları değiştirmek için kullanılacak ve bir tıklama olay işleyicisine ihtiyacı var. Öyleyse, click olay işleyicisini şöyle yazalım:

 const onClickHandler = () => { setTheme(); }

Şimdi, mevcut tema Blue ise yeni temayı Red olarak ayarlamak istiyoruz ve bunun tersi de geçerlidir. Bir if ifadesi kullanmak yerine, bunu yapmanın daha uygun bir yolu JavaScript'teki üçlü operatörün yardımıdır.

 setTheme( theme === "red"? "blue": "red");

Şimdi, onClick işleyicimizi yazdık. Bu düğme öğesini App bileşenine ekleyelim:

 <button onClick = {onClickHandler}>Change theme</button>

Ayrıca Text bileşeninin theme props değerini de theme durumuna değiştirelim.

 <Text theme={theme}/>

Şimdi, buna sahip olmalıyız:

 import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; function App() { const[theme, setTheme] = React.useState("red"); const onClickHandler = () => { setTheme( theme === "red"? "blue": "red"); } return ( <div> <Text theme={theme}/> <button onClick = {onClickHandler}>Change theme</button> </div> ); } function Text({theme}) { return( <h1 style = {{ color: `${theme}` }}>{theme}</h1> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);

Artık iki temamız arasında geçiş yapabiliriz. Ancak, bu çok daha büyük bir uygulama olsaydı, temayı derinlemesine iç içe bileşenlerde kullanmak zor olurdu ve kod hantal hale gelir.

Bağlam API'sine Giriş

Bağlam API'sini tanıtmama izin verin. React belgelerine göre:

"Bağlam, verileri her düzeyde manuel olarak aşağı aktarmak zorunda kalmadan bileşen ağacından geçirmenin bir yolunu sağlar."

Daha derinlemesine bir tanım için, belirli verileri bileşen ağacının tamamında, o bileşen ne kadar iç içe geçmiş olursa olsun tüm bileşenler için kullanılabilir hale getirmeniz için bir yol sağlar.

Şu örneğe bakalım:

 const App = () => { return( <ParentComponent theme = "light"/> ); } const ParentComponent = (props) => ( <Child theme = {props.theme} /> ) const Child = (props) => ( <Grandchild theme = {props.theme} /> ) const Grandchild = (props) => ( <p>Theme: {props.theme}</p> )

Yukarıdaki örnekte, uygulama theme , Theme adlı ParentComponent bir props kullanarak belirttik. GrandChild bileşeni olan ihtiyaç duyulan yere ulaşmak için bu aksesuarları bileşen ağacındaki tüm bileşenlere geçirmemiz gerekiyordu. ChildComponent tema aksesuarlarıyla hiçbir ilgisi yoktu, sadece bir aracı olarak kullanıldı.

Şimdi GrandChild bileşeninin en üstteki örnekte olduğundan daha derin bir şekilde iç içe olduğunu hayal edin. Tema aksesuarlarını burada yaptığımız gibi geçmemiz gerekecekti ki bu hantal olurdu. Context çözdüğü sorun budur. Context ile, bileşen ağacındaki her bileşen, bağlamımıza koymaya karar verdiğimiz tüm verilere erişebilir.

Context Başlayalım

Makalenin başında oluşturduğumuz tema değiştirme düğmesini Context API ile çoğaltmanın zamanı geldi. Bu sefer tema değiştiricimiz ayrı bir bileşen olacak. Context kullanarak React uygulamamızın temasını değiştiren bir ThemeToggler bileşeni oluşturacağız.

Öncelikle React uygulamamızı başlatalım. (Ben create-react-app kullanmayı tercih ediyorum ama siz istediğiniz yöntemi kullanabilirsiniz.)

React projenizi başlattıktan sonra /src klasörünüzde ThemeContext.js adlı bir dosya oluşturun. Ayrıca /context adında bir klasör oluşturabilir ve isterseniz ThemeContext dosyanızı oraya yerleştirebilirsiniz.

Şimdi, devam edelim.

Bağlam API'nizi Oluşturma

Tema bağlamımızı ThemeContext.js dosyamızda oluşturacağız.

Bir bağlam oluşturmak için, bir bağlam nesnesi oluşturan React.createContext kullanırız. Herhangi bir şeyi argüman olarak React.createContext . Bu durumda, mevcut tema modu olan bir dizeye geçeceğiz. Şimdi mevcut tema modumuz “hafif” tema modudur.

 import React from "react"; const ThemeContext = React.createContext("light"); export default ThemeContext;

Bu içeriği tüm React bileşenlerimiz için kullanılabilir hale getirmek için bir Sağlayıcı kullanmalıyız. Sağlayıcı nedir? React belgelerine göre, her bağlam nesnesi, tüketen bileşenlerin bağlam değişikliklerine abone olmasına izin veren bir Sağlayıcı React bileşeniyle birlikte gelir . İçeriğin diğer bileşenler tarafından tüketilmesine izin veren sağlayıcıdır. Bununla birlikte, sağlayıcımızı oluşturalım.

App.js dosyanıza gidin. Sağlayıcımızı oluşturmak için ThemeContext içe aktarmalıyız.

ThemeContext içe aktarıldıktan sonra, App bileşenimizin içeriğini ThemeContext.Provider etiketleri içine almalı ve ThemeContext.Provider bileşenine, bileşen ağacımız için kullanılabilir kılmak istediğimiz verileri içerecek, value adı verilen bir destek vermeliyiz.

 function App() { const theme = "light"; return ( <ThemeContext.Provider value = {theme}> <div> </div> </ThemeContext.Provider> ); }

Yani artık “ışık” değeri tüm bileşenlerimizde mevcuttur (ki bunu birazdan yazacağız).

Tema Dosyamızı Oluşturmak

Şimdi hem açık hem de koyu temalarımız için farklı renk değerlerini içerecek tema dosyamızı oluşturacağız. /src klasörünüzde Colors.js adlı bir dosya oluşturun.

AppTheme AppTheme adında bir nesne oluşturacağız. Bu nesne, temalarımızın renklerini içerecektir. İşiniz bittiğinde, AppTheme nesnesini şu şekilde dışa aktarın:

 const AppTheme = { light: { textColor: "#000", backgroundColor: "#fff" }, dark: { textColor: "#fff", backgroundColor: "#333" } } export default AppTheme;

Şimdi farklı React bileşenlerimizi oluşturmaya başlama zamanı.

React Bileşenlerimizi Oluşturma

Aşağıdaki bileşenleri oluşturalım:

  • Header
  • ThemeToggler
  • MainWithClass

Header.jsx

 import React from "react"; import ThemeToggler from "./ThemeToggler"; const headerStyles = { padding: "1rem", display: "flex", justifyContent: "space-between", alignItems: "center" } const Header = () => { return( <header style = {headerStyles}> <h1>Context API</h1> <ThemeToggler /> </header> ); } export default Header;

ThemeToggler.jsx

(Şimdilik sadece boş bir div döndüreceğiz.)

 import React from "react"; import ThemeContext from "../Context/ThemeContext"; const themeTogglerStyle = { cursor: "pointer" } const ThemeToggler = () => { return( <div style = {themeTogglerStyle}> </div> ); } export default ThemeToggler;

Sınıf Tabanlı Bileşenlerle Bağlamı Tüketmek

Burada ThemeContext değerini kullanacağız. Bildiğiniz gibi , React'te bileşen yazmak için iki yöntemimiz var: işlevler veya sınıflar aracılığıyla. Her iki yöntemde de bağlam kullanım süreci farklıdır, bu nedenle uygulamamızın ana bölümü olarak hizmet edecek iki bileşen oluşturacağız: MainWithClass ve MainWithFunction .

MainWithClass ile başlayalım.

MainWithClass.jsx

ThemeContext ve AppTheme dosyalarımızı içe aktarmamız gerekecek. Bu yapıldıktan sonra, bir render yönteminden JSX'imizi döndüren bir sınıf yazacağız. Şimdi bağlamımızı tüketmeliyiz. Bunu sınıf tabanlı bileşenlerle yapmanın iki yöntemi vardır:

  1. İlk yöntem Class.contextType aracılığıyladır.

    Bu yöntemi kullanmak için, ThemeContext bağlam nesnesini contextType özelliğine atadık. Bundan sonra, this.context kullanarak bağlam değerine erişebileceğiz. Buna herhangi bir yaşam döngüsü yönteminde ve hatta oluşturma yönteminde de başvurabilirsiniz.

     import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component{ constructor(){ super(); } static contextType = ThemeContext; render(){ const currentTheme = AppTheme[this.context]; return( <main></main> ); } }

    contextType özelliğine ThemeContext atadıktan sonra, currentTheme değişkeninde mevcut theme nesnesini kaydettim.

    Şimdi, currentTheme değişkeninden renkleri alacağız ve bunları bazı işaretlemeleri biçimlendirmek için kullanacağız.
     render() { const currentTheme = AppTheme[this.context]; return ( <main style={{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main>

    Bu kadar! Ancak bu yöntem, yalnızca bir bağlam tüketmenizi sınırlar.
  2. İkinci yöntem, bir Tüketici kullanımını içeren ThemeContext.Consumer . Her bağlam nesnesi ayrıca sınıf tabanlı bir bileşende kullanılabilen bir Tüketici Tepkisi bileşeniyle birlikte gelir. Tüketici bileşeni, bir çocuğu işlev olarak alır ve bu işlev bir React düğümü döndürür. Geçerli bağlam değeri, bu işleve bir bağımsız değişken olarak iletilir.

    Şimdi MainWithClass bileşenimizdeki kodu bununla değiştirelim:
     class Main extends Component { constructor() { super(); this.state = { } } render(){ return( <ThemeContext.Consumer> { (theme) => { const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ) } } </ThemeContext.Consumer> ); } }

    Gördüğünüz gibi ThemeContext “theme” adını verdiğimiz mevcut değerini kullandık ve o tema modu için renk değerlerini alıp currentTheme değişkenine atadık. Bu yöntemle birden fazla Tüketici kullanabilirsiniz.

Bunlar, sınıf tabanlı bileşenlerle bağlam tüketmenin iki yöntemidir.

İşlevsel Bileşenlerle Bağlam Kullanmak

İşlevsel bileşenlerle bağlam tüketmek, sınıf tabanlı bileşenlerle yapmaktan daha kolay ve daha az sıkıcıdır. Bağlamı işlevsel bir bileşende kullanmak için useContext adlı bir kanca kullanacağız.

ThemeContext işlevsel bir bileşenle tüketmek şöyle görünür:

 const Main = () => { const theme = useContext(ThemeContext); const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } export default Main;

Gördüğünüz gibi, tek yapmamız gereken, argüman olarak geçirilen ThemeContext ile useContext kullanmaktı.

Not : Sonuçları görebilmek için App.js dosyasında bu farklı bileşenleri kullanmanız gerekmektedir.

ThemeToggler Bileşeniyle Güncelleme

Şimdi ThemeToggler bileşenimiz üzerinde çalışacağız. Açık ve koyu temalar arasında geçiş yapabilmemiz gerekiyor. Bunu yapmak için ThemeContext.js dosyamızı düzenlememiz gerekecek. React.createContext artık argüman olarak useState kancasının sonucuna benzeyen bir nesne alacaktır.

 const ThemeContext = React.createContext(["light", () => {}]);

React.createContext işlevine bir dizi ilettik. Dizideki ilk öğe, geçerli tema modudur ve ikinci öğe, temayı güncellemek için kullanılacak işlevdir. Dediğim gibi, bu sadece bir useState kancasının sonucuna benziyor, ancak tam olarak bir useState kancasının sonucu değil.

Şimdi App.js dosyamızı düzenleyeceğiz. Sağlayıcıya iletilen değeri bir useState kancasıyla değiştirmemiz gerekiyor. Şimdi Tema Bağlamımızın değeri, varsayılan değeri "hafif" olan bir useState .

 function App() { const themeHook = useState("light"); return ( <ThemeContext.Provider value = {themeHook}> <div> <Header /> <Main /> </div> </ThemeContext.Provider> ); }

ThemeToggler Bileşenimizi Yazma

Şimdi ThemeToggler bileşenimizi gerçekten yazalım:

 import React,{useContext} from "react"; import ThemeContext from "../Context/ThemeContext"; const themeTogglerStyle = { cursor: "pointer" } const ThemeToggler = () => { const[themeMode, setThemeMode] = useContext(ThemeContext); return( <div style = {themeTogglerStyle} onClick = {() => {setThemeMode(themeMode === "light"? "dark": "light")}}> <span title = "switch theme"> {themeMode === "light" ? "" : "️"} </span> </div> ); } export default ThemeToggler;

Tema bağlamımızın değeri artık bir kanca olduğundan, ne zaman üzerinde useContext , bir dizi döndürür. Yıkımı kullanarak, dizideki öğeleri yakalayabildik. Ardından ThemeToggler için bir onClick olay işleyicisi yazdık. Bu kodla, tema değiştirici tıklandığında, uygulamamızın temasını değiştirecektir.

Şimdi Main bileşenimizin farklı sürümlerini düzenleyeceğiz.

MainWithClass Bileşenimizi Düzenleme

  1. MainWithClass bileşeninin Class.contextType yöntemini kullanan sürümü:
     import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component{ constructor(){ super(); } static contextType = ThemeContext; render(){ const currentTheme = AppTheme[this.context[0]]; return( <main style={{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } }
  2. ThemeContext.Consumer yöntemini kullanan MainWithClass bileşeninin sürümü:
     import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component { constructor() { super(); this.state = {} } render() { return ( <ThemeContext.Consumer> { ([theme]) => { const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ) } } </ThemeContext.Consumer> ); } } export default Main;

MainWithFunction Bileşenimizi Düzenleme

MainWithFunction Bileşeni aşağıdaki gibi düzenlenmelidir:

 import React, { useContext } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; const Main = () => { const theme = useContext(ThemeContext)[0]; const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } export default Main;

Çözüm

Bu kadar! Context API kullanarak React uygulamamız için iki tema modu uygulamayı başardık.

Bu süreçte şunları öğrendik:

  • Bağlam API'sinin ne olduğu ve çözdüğü sorun;
  • Bağlam API'si ne zaman kullanılır;
  • Context oluşturma ve hem işlevsel hem de sınıf tabanlı bileşenlerde tüketme.

SmashingMag'de Daha Fazla Okuma :

  • Modern Web Uygulamalarında Stil Oluşturma
  • Ionic And React ile Mobil Uygulamalar Oluşturma
  • Web Paketi ve Çalışma Kutusu ile PWA Oluşturun
  • MutationObserver API'sini Tanımak